第30课 驱动调试

本文详细介绍了Linux驱动调试的方法,包括printk的原理与使用,如何将驱动调试信息写入proc文件系统,以及如何根据pc值分析段错误。文章通过实例演示了printk在驱动程序中的应用,以及如何通过proc文件系统实现自定义的日志记录。同时,文章还探讨了如何根据段错误的pc值确定出错代码位置,分析内核模块和编入内核的驱动程序中的错误。最后,提到了自制寄存器编辑器和通过修改系统时钟中断来定位系统僵死问题的技巧。

第30课 驱动调试

  1. 打印:printk,自制proc文件
  2. 自制工具
  3. 根据内核打印的段错误信息分析
  4. 修改内核

第1.1节 驱动调试之printk原理

在这里插入图片描述

1. 内核处理uboot传入的参数:

使用printk将内核的一些信息打印出来(通过串口或者LCD屏幕),那么printk函数中就必然会有操作这些硬件的实现。但是printk最终会将信息打印到哪里呢?(串口或者LCD)这是由uboot中的 bootargs 参数设置的,比如:“set bootargs console=ttySAC0” 就是将打印信息输出至串口0。
在这里插入图片描述
为了弄明白printk是如何根据bootargs命令行参数找到对应的硬件操作函数的,现在在内核中搜索“console=”
但是这样搜索的效率太低,有个小技巧:在任意位置写出“console=”,然后右键—>查找引用(lookup Reference):
在这里插入图片描述
在这里插入图片描述
这时已经找到了我们想要的结果。
在这里插入图片描述
这里可以做以下猜测:当内核从bootargs命令行得到“console=”前缀参数的时候,就利用后面的console_setup函数来处理该前缀。
进入到console_setup函数中:
在这里插入图片描述
这里的str就是“console=”前缀后面带的字符串“ttySAC0”
UBOOT传入console=ttySAC0 console=tty1
在这里插入图片描述
问:怎么根据 ttySAC0 这个参数找到对应的硬件操作函数??
在这里插入图片描述

2. console硬件对应的驱动程序:

硬件的驱动程序中都会注册一个console结构体,该console结构体中会有相应的名字(.name)和相应的write函数(负责发送信息到相应的控制台终端)。

通过 register_console 注册控制台来使用具体的硬件。

注册函数register_console中会比较属于某个硬件(串口、LCD)的结构体中的名字(name属性)和console_setup 函数中接收到的来自bootargs命令行传来的那个名字(如,ttySAC0),如果一样,则在调用printk打印时就用对应硬件结构体中的write函数进行信息的输出。
在这里插入图片描述
在内核中搜索register_console 函数找到s3c对应的文件:
在这里插入图片描述
这里可以看到向内核注册了console结构体:
在这里插入图片描述

3. printk的具体实现:

这里可以猜测,printk就是通过调用console结构体中的write函数来进行输出的。
在这里插入图片描述
这里的 log_buf 是什么?—其实是一个字符数组(指向数组的指针)
在这里插入图片描述
在放入log_buf之前还要对其中的数据稍作处理:
-----在打印数据之前,要对数据的级别做处理:-----打印级别
在这里插入图片描述
在这里插入图片描述
处理完了之后就会将数据放入log_buf中。

问:既然这些信息在内核中有,那我们能否复现其中的信息??

-----通过 “dmesg” 命令即可将 log_buf 中的数据信息取出来再打印在显示终端上。
在这里插入图片描述
在这里插入图片描述
注意:这里可以通过设置bootargs参数将信息同时打印在串口和LCD上:在这里插入图片描述
call_console_drivers 函数中会根据log_buf中数据的级别来选择要打印的数据。(log_buf中有所有的打印数据,不管级别是多少;但是这些数据是否打印就要根据级别来选择了)

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

总结:

在这里插入图片描述

第1.2节 驱动调试之printk使用

实验:

在之前的first_drv.c 点灯驱动程序中人为设置一个错误:
在这里插入图片描述
在使用寄存器的时候没有用ioremap,而是直接使用物理地址。

编译,装载之后出错:
在这里插入图片描述
这时候用printk 来找错误:
先分析:
在这里插入图片描述
应用程序调用到open函数,就会进入到内核的驱动程序中:
在这里插入图片描述
在内核驱动程序的open函数中加打印语句:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在实际操作过程中,可以用折半加打印的方式进行。

重新编译,装载驱动:
在这里插入图片描述
接下来运行应用程序(test测试程序):
在这里插入图片描述
看到打印出了26行。

在这里插入图片描述
程序死的原因就是访问了非法地址,这时就可以轻松定位到出错的地方了。

下面加入打印级别:

给所有的printk加入打印级别:
在这里插入图片描述
从之前分析printk的原理中知道,消息的打印级别必须小于某个数值才能被打印:

在这里插入图片描述
我们自己的printk打印级别设置为了“7”:
在这里插入图片描述
可以看到装载和卸载过程都没有打印信息:
在这里插入图片描述
这是因为我们自己设置的打印级别并不满足打印条件:

msg_log_level < console_loglevel

问:那我们能不能自己设置打印条件的上限console_loglevel呢??

在这里插入图片描述
在这里插入图片描述
可以看到这里的console_loglevel被设置为了“7”,因此我们的打印信息不会被打印出来。

修改这个文件后发现打印信息出来了:

在这里插入图片描述

第1.3节 驱动调试之打印到proc虚拟文件

“dmesg” 命令可以在启动内核后复现之前打印过的内核信息。

但是该命令肯定是从一个文件中读取了内核打印信息-----就是下图中的这个文件:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值