内核驱动调试常用方法

前面我们说了裸机调试常用方法,当然,在linux内核上进行驱动开发也也有常见方法。一般为打印法(printk)

1.打印法(printk)
打印法本质上和裸机里面的打印差不多,都是定位到某个硬件进行打印,只不过裸机一般就是串口打印,而内核打印可以时串口也可以是lcd,另外,内核已经有已经封装好的打印函数printk,不用像裸机那样自己封装。

内核具体打印到哪个硬件设备是由uboot传入的启动参数决定的,其格式为console=设备名,这里可以传多个这样格式相同但设备名不同的参数,意味着信息可以打印到多个设备里面去,如果不传这个参数,就算调用printk也不会打印成功。

printk的工作原理为:根据uboot传的设备名参数,去找到一个匹配的硬件设备,因为像lcd和串口这样的硬件初始化时也会创建自己的设备文件,它们在注册设备文件时会去匹配自己的设备名和传入的设备名,如果匹配上了就是调用自己的写函数进行打印。

printk可以在要打印的字符串前面加打印级别,具体格式为printk(“<打印级别>str”),如果打印级别小于默认级别则会打印,如果没有加打印级别则默认为4,这些打印信息会先被存放到一个缓冲数组里面。dmesg命令就是从这个数组里打印的数据,最后会调用写函数从数组里取出数据发送出去,也就是printk的打印结果。

注意:测试好后如果不想让打印信息输出,则可以修改默认打印级别来控制,因为只有设置的打印级别小于默认打印级别才会打印,则把默认级别修改为0肯定不会打印,可以通过系统启动后修改配置文件来修改,也可以在uboot启动参数里添加loglevel=某个值来修改,传参的方式是推荐使用的。

2.根据内核打印的段错误信息分析
当程序中有某个错误时,在执行或装载的时候会打印出错误信息,这些信息一般包括发生错误的pc值(指令地址),执行错误指令时各个寄存器的值,当前进程的名称,栈信息,回溯信息(函数调用关系)

通过打印信息可以查看到当前错误的指定地址,然后判断给地址是属于内核模块还是自己装载模块,判断方法为:打开内核的System.map文件,如果这个地址在这个文件里,这该错误属于内核错误,然后对Linux编译好的文件进行反汇编,具体定位到那条错误地址的指定排查即可。

如果时外部加载的模块,则用cat /proc/kallsyms命令可以查看加载的函数地址,然后找到一个比当前打印的错误指令地址,这个地址模块对应的模块应该就是错误地址的模块,然后对该模块进行反汇编,在反汇编文件里可以查到错误指定地址,据此排查即可。需要注意的是,加载进内核的地址可能和反汇编出来的地址不一样,一般是基地址不一样,地址偏移量都是一样的,例如反汇编地址0x00000011,错误地址0x00000016,则加载到内核地址为0xb0000011,错误地址0xb0000016。

除了通过错误指令地址排查,也可以通过回溯信息查看,但是这个前提是内核配置了能打印回溯信息,具体配置为:CONFIG_FRAME_POINTER=y,通过这种回溯信息可以查看到函数之间的调用关系,为什么需要知道调用关系呢,因为一个函数可能被多个函数调用,也就是有多个调用链,可能是前面的调用链上的函数导致了该函数错误,所以这时候就需要知道调用关系了。

当然,如果内核没有打印回溯信息,自己可以通过栈信息推导出调用链,因为当前错误指令地址会被打印,而通过该指令可以具体定位到是哪个模块的函数出了错(剧吐定位方法和前面说过的一样),然后反汇编该模块,通过对照汇编码和栈信息就可以找出该函数的lr寄存器保存的调用函数下一条指令的pc值,该pc一定属于调用函数的一本分,通过搜索就可以找到调用函数,依次按此方法进行递归查找,最终就会找到一条完整的调用关系链。

3.自制工具法
所谓自制工具就是我们自己编写一个驱动程序来读写寄存器的值,这样就可以查看某些寄存器的值来进行问题排查,具体用法为应用程序通过传入寄存器的值和读写标识等控制参数来调用,该方法需要对相关硬件的寄存器和操作特别了解。

4.修改内核定位系统僵死问题
所谓系统僵死就是系统卡住不动,一般就是系统里有死循环代码或其他原因,要排查出具体是哪一段代码导致的就需要在内核做手脚,因为此时系统僵死其他方法也不好使。

内核做手脚一般也就是在内核里面打印信息,因为系统时钟中断只要不关机就会一直运行,此时可以在该中断的处理函数或者中断调用函数里打印出当前进程id以及进程名和pc值,这个进程名就是僵死的进程,pc值就是具体僵死代码的指令地址,如此就可以通过前面所说的方法定位具体问题。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值