作者:手机用户2602932547 | 来源:互联网 | 2023-07-07 09:13
第十八章调试0.总结oops内核的调试配置用Git进行二分搜索bug总会有,简洁描述发给LKML1.准备开始在用户级的程序里,bug表现比较直接;在内核中却不清晰。2.内核中的bug多种多样、变
第十八章 调试
0.总结
- oops
- 内核的调试配置
- 用Git进行二分搜索
- bug总会有,简洁描述发给LKML
1. 准备开始
- 在用户级的程序里,bug表现比较直接;在内核中却不清晰。
2. 内核中的bug
- 多种多样、变化多端。
- 引用空指针会产生一个oops;垃圾数据会导致系统崩溃。
- 定时限制和竞争条件都允许多个线程在内核中同时运行产生的结果。
3. 通过打印来调试
3.1 健壮性
3.2 日志等级
- printk()可以指定一个日志级别【与printf()最大区别】。
- 内核判断是否在终端上打印消息的依据。
指定一个记录级别的方式:
- KERN_WARING和KERN_DEGUG是中的简单宏定义。
- 内核用指定的记录等级和当前终端的记录等级console_loglevel来决定是不是向终端上打印。
- 默认级别:KERN_WARNING。
按照自己想法赋予记录等级方法:
3.3 记录缓冲区
3.4 syslogd和klogd
3.5 从printf()到printk()的转换
4. oops
- 内核告知用户有不幸发生的最常见方式。
内核发布oops会向终端输出的内容:
1.错误消息;
2.寄存器中保存的信息;
3.可供跟踪的回溯线索。
oops发生时间出现的状况:
oops包含信息:
4.1 ksymoops
4.2 kallsyms
- CONFIG_KALLSYMS 定义配置选项启用。
- CONFIG_KALLSYMS_ALL 存放函数名称;存放所有符号名称。
- CONFIG_KALLSYMS_EXTRA_PASS 引起内核构建中再次忽略内核的目标代码。
5. 内核调试配置选项
- 在内核配置编辑器的内核开发菜单项中,依赖CONFIG_DEBUG_KERNEL。
6. 引发bug并打印信息
- 常用BUG()和BUG_ON()。
- 调用会引发oops
7. 神奇的系统请求键
8. 内核调试器的传奇
8.1 gdb
8.2 kgdb
- 是一个补丁,可在远端主机上通过串口利用gdb的所有功能对内核进行调试。
9. 探测系统
9.1 用UID作为选择条件
- 利用把用户id(UID)作为选择条件实现新算法加入:
9.2 使用条件变量
使用前提:
代码与进程无关;
希望有一个针对所有情况都能用的机制来控制某个特性。
只需创建一个全局变量作为一个选择开关。
9.3 使用统计量
9.4 重复频率限制
- 为了避免调试信息发生井喷,可以每隔几秒执行一次操作。
10. 用二分法找出引发罪恶的变更
11. 使用Git进行二分搜索
$ git bisect start ;进行二分搜索
$ git bisect bad ;引发提供一个出现问题的最高内核版本
$ git bisect bad ;若当前内核版本就是bug的元凶,那不必提供内核版本
$ git bisect good v2.6.28 ;最新可正常运行的内核版本
$ git bisect good ;这个版本正常
$ git bisect bad ;这个版本有异常
12. 当所有努力都失败时:社区