linux驱动源码阅读之情景分析法实践指南
1. 情景分析法必须确立一个情景,此情景满足以下条件:
# a.满足自己的学习目标
# b.该情景内的代码,应该只能被执行1次.譬如,分析usb进行数据传输的过程. 那么在执行该情景前,应该将
# 所以的USB设备拔出, 或者将它们对应的驱动取消执行.
# 再譬如, 要分析kmalloc()的执行过程, 那么我应该在该kmalloc第一次被执行处,加上一句while(1), 防止后续又
# 有kmalloc()被执行.
# c.若该情景需要用户应用, 譬如应用获取按键事件等. 所要执行的应用程序应尽量得到其源码, 或者自行编写或搜索相关例程.
# 拥有源码后, 就可以将不必要的代码删除, 减少关联驱动的阅读.
2. 情景分析法实践流程:
# a. 由上至下的代码简化. 由上至下,即由应用程序=>驱动框架=>硬件驱动.
# 应用程序的一句ioctl(), 可能涉及驱动的几百个函数的执行. 若是我们能先尽量地简化应用程序,或驱动框架,会大大地
# 减少代码阅读量.
# b. 批量添加函数名打印. 根据打印, 可以一一对被执行的函数进行简化. 具体添加打印方法,见
# https://blog.csdn.net/weixin_45154862/article/details/127192739
# c. 集合所有被简化的函数, 进行代码分析.
3. 细节说明之 函数简化:
# 去掉判断语句,循环语句, 宏定义的语句, 总之去掉所以需要我们进行分析判断, 耗费脑力的代码.
# 而最终简化的结果是, 我们可以无需依靠打印,开发板的运行输出, 便可以靠阅读代码,知道代码的执行流程.
# 函数简化的范围: 我们分析的是驱动代码, 其他非该驱动框架或驱动的代码无需简化分析. 譬如kmalloc.
# 一般,范围会限制在该驱动框架或驱动所在文件夹内.
# z. 直接删除函数
# 在对某个函数进行简化前, 我们可以试着将该函数删除, 会有30%的概率,情景依旧正常执行!
# 这样的结果是喜闻乐见的,因为一个函数,可能会嵌套几十个函数, 那么我们就可以少简化几十个函数,
# 少分析几十个函数. 大大地减少工作量.
# 因此简化前,请先执行此步骤.
# a. 保留副本
# 需要简化的函数, 应保留其副本(函数原文件处,复制一份,并重命令), 方便代码分析时回看.
# 而我们的简化工作就直接在原函数进行.
# b. 独立函数的执行.
# 若某函数被执行了多次, 且每次的执行, 执行流程的不同.可以将该函数的代码复制多份, 并重命名,
# 以独立每次函数的执行. 这样,简化工作就在其函数副本内执行, 这区别于步骤a. 每一个函数的副本,
# 若想它们被执行, 需要在头文件添加声明, 将会增加工作量. 这也就是步骤a直接修改原函数,而非副本函数的理由.
# 譬如:
# 处理前:
test();
test();
test();
# 处理后:
test1();
test2();
test3();
# c. 去掉所有的判断语句的分支, 仅保留被执行的代码,及其判断条件.
# 譬如:
# 简化前:
void test(int a,int b)
{
int c;
if(a>9) {
xxxx; /* 被执行 */
} else if (b<9) {
xxxx;
}
}
# 简化后
void test(int a,int b)
{
int c;
if(a>9) {
xxxx; /* 被执行 */
}
}
# d. 去掉循环
# 譬如:
# 简化前
i=0;
while(i<get_count()){
set_index(i);
i++;
}
# 简化后
/* get_count()的返回值为3 */
i=0;
set_index(i);
i=1;
set_index(i);
i=2;
set_index(i);
# 这时, set_index()函数被执行了多次.可以使用b步骤进行处理.
# e. 去掉宏定义
# 譬如:
# 简化前:
# xxx.h
#define TEST(a,b) a>b:3?4
xxx.c
TEST(5,6);
#简化后:
xxx.c
5>6:3?4
# f. 删除指针赋值语句
# 太多的指针变量, 使得结构体间的关系错综复杂.但其实许多的指针,在当前情景内,是不被使用的,
# 将它们删除, 可以减少代码分析时的工作量. 不仅是指针, 含有队列的入队,出队等语句, 也可删除的
# 都尽量删除.
4. 细节说明之 代码分析
# a. 集合所有简化后的,需要被执行的, 该驱动相关的, 函数到一个文件内. 依据函数的嵌套关系,将函数源码补充完全.
# 主要目的是方便分析, 和进行代码标注.
# 譬如:
int test(void)
{
get_index();
void get_index(void)
{
set_type(c);
void set_type(struct type a)
{
g_type = a;
}
}
}
# b. 结构体成员关系标注
# 使用<tagx> 指示 某一操作的对象,以及操作过程.
# 对象或成员处注有<tagx>, 操作处也注有 <tagx>, 可以实现跳转,通过手动搜索<tagx>.
# 譬如, 这里的<tagx> 可以记录该成员在何处被分配内存, 或被赋值.
struct machine {
struct tv b;
};
struct machine a;
-> struct tv *b; <tag3>
int machine_type_create(struct machine *mac)
{
mac->b = kmalloc(); <tag3>
}
# <point to objx> 意为此指针指向objx, <objx> 在objx 处有标注.
# 譬如一下, <point to obj6> 表明b成员指向sony_tv. 而<tag5> 标注此赋值是在何处进行的.
strct machine a;
->struc tv *b; <point to obj6> <tag5>
struct tv sony_tv; <obj6>
int get_tv(struct machine *mac)
{
mac->b = &sony_tv; <tag5>
}
# <add to listx> 意为将此list_head加入 listx, <listx> 在链表头处有标注.
#https://gitee.com/suiren/usb2hdmi/blob/master/drm_read.c
#drm_read.c一文,是完全使用本文的代码阅读方法, 而获得的驱动阅读总结, 也可作为参考.
linux驱动源码阅读之情景分析法实践指南相关推荐
- [Linux] USB-Storage驱动 源码阅读笔记(一)
USB-Storage驱动 源码阅读笔记--从USB子系统开始 最近在研究U盘的驱动,遇到很多难以理解的问题,虽然之前也参考过一些很不错的书籍如:<USB那些事>,但最终还是觉得下载一份最 ...
- r8169驱动源码阅读记录
r8169驱动源码阅读记录 初始化 发包 收包 源码地址:linux-4.19.90\drivers\net\ethernet\realtek\r8169.c 源码阅读环境:Windows 搭建 op ...
- 【转载】ubuntu下linux内核源码阅读工具和调试方法总结
http://blog.chinaunix.net/space.php?uid=20940095&do=blog&cuid=2377369 一 linux内核源码阅读工具 window ...
- Linux内核源码阅读以及工具(转)
Linux内核源码阅读以及工具(转) 转载地址:Linux内核源码阅读以及工具(转)
- Linux内核学习(五):linux kernel源码结构以及makefile分析
Linux内核学习(五):linux kernel源码结构以及makefile分析 前面我们知道了linux内核镜像的生成.加载以及加载工具uboot. 这里我们来看看linux内核的源码的宏观东西, ...
- 米尔科技 Z-turn XC7Z010 Linux驱动源码路径
米尔科技 Z-turn XC7Z010 Linux驱动源码路径 网址:http://www.myir-tech.com/bbs/thread-6999-1-1.html Z-turn XC7Z010 ...
- Linux内核源码阅读以及工具详解
接上篇Linux内核源码下载方法 这篇总结了如何利用source insight对Linux内核代码进行阅读和学习(资料来源于网络) 随着linux的逐步普及,现在有不少人对于Linux的安装及设置已 ...
- java collection源码_jdk源码阅读Collection实例分析
jdk源码阅读Collection详解 见过一句夸张的话,叫做"没有阅读过jdk源码的人不算学过java".从今天起开始精读源码.而适合精读的源码无非就是java.io,.util ...
- linux实现自己的write函数,Linux 内核源码阅读 - write 系统调用的实现
最近在看write系统调用的实现,虽然还有一下细节不是很清楚,但是大致的实现机理还是有一定的理解了.总结如下: 这里假设最普通的情况,不考虑Direct IO 的情况.从全家的高度看,要往一个文件中写 ...
最新文章
- MongoDB性能测试代码
- BFC(Box Formatting Context)的原理
- matlab GUI figure置右上角
- python困难_Python开发总感觉困难重重,可能是你没用上这些开发工具
- 大剑无锋之如何查看一个java进程的堆内存使用情况(jps,jstack,jmap)【面试推荐】
- ps的初级教程:去痘痘-庞姿姿
- 英语3500词(二) your dream lover主题 (2022.1.14)
- 牛客网SQL实战二刷 | Day1
- 5-2本题要求对两个整数a和b,输出其中较大的数。
- Squid+MRTG实现完善的缓存代理和http服务加速代理
- IT小盆友:注意20种习惯最耗元气
- 导出excel文件后,显示文件损坏
- 计算机导论二进制小数乘法,二进制计算
- [整理]几个好的嵌入式linux学习网站和博客
- css中的auto属性
- 开发原生的 Google 眼镜应用 【已翻译100%】(1/2)
- iPhone X下界面满屏展示
- java程序设计教程试题_java程序设计试题库.doc
- 服务器额定功率和实际功率_商业服务器解决方案,提高功率和效率
- 开课啦!图观™应用编辑器 零基础入门课(第一讲)
热门文章
- asp.net中HTML控件和web控件的简单理解
- offsetLeft深入研究
- 在Ubuntu上装CLPACK,并跑出ELSDc的代码
- 二线城市的JAVA工程师,从一二线城市回到三四线城市的工程师们,是否可以分享一下你们现在的工作与状态?...
- 成事的百条铁律(21-40)
- 成考大专要英语和计算机吗,成人高考都需要考英语吗
- Excel写保护怎么破解
- c#获取本地ip地址网关子网掩码_详细介绍winformC#获得Mac地址,IP地址,子网掩码,默认网关的代码实例(图)...
- 黄聪:Fiddler对安卓应用手机抓包图文教程
- 群雄逐鹿 百家争鸣 | 华云数据荣获2021信创“大比武”总决赛全国第二名