《Linux内核设计与实现》 第十八章学习笔记
调 试
一、准备开始
- 一个bug
- 一个藏匿bug的内核版本
- 相关内核代码的知识和运气
- 知道这个bug最早出现在哪个内核版本中。
1、想要成功进行调试:
- 让这些错误重现
- 抽象出问题
- 从代码中搜索
二、内核中的bug
从隐藏在源代码中的错误到展现在目击者面前的bug,往往是经历一系列连锁反应的事件才可能触发的。内核确实有一些独特的问题需要考虑,像定时限制和竞争条件等,它们都是允许多个线程在内核中同时运行产生的结果。
三、通过打印来调试
内核提供的打印函数printk()和C 库提供的printf()函数功能几乎相同。
1、健壮性
- 健壮性是printk() 函数最容易让人们接受的一个特质..可以在中断上下文和进程上下中被调用,可以在任何持有锁时被调用,可以在多处理器上同时被调用,而且调用者连锁都不必使用。
- 解决的办单是提供一个printk() 的变体函数一一early_printk(),这个函数在启动过程的初期就具有在终端上打印的能力,它的功能与prink()完全相同,区别仅仅在于名字和能够更早地工作,不过,由于该函数在一些内核支持的硬件体系结构上无法实现,所以这种办法峡少可移植性。
2、日志等级
- printk()和printf()在使用上最主要的区别就是前者可以指定一个日志级别, 内核根据这个级别来判断是否在终端上打印消息。内核把级别比某个特定值低的所有消息显示在终端上。
3、记录缓冲区
- 内核消息都被保存在一个LOG_BUF_LEN 大小的环形队列中。该缓冲区大小可以在编译时通过设置CONFIG_LOG_BUF_SHIFf 进行调整。在单处理器的系统上其默认值是16。如果消息队列已经达到最大值,那么如果再有printk()调用,新消息将覆盖队列中的老消息。这个记录缓冲区之所以称为环形,是因为它的读写都是按照环形队列方式进行操作的。
- 环形缓冲区的唯一缺点一一可能会丢失消息
4、syslogd 和klogd
- syslogd 守护进程把它接收到的所有消息添加进一个文件中,该文件默认是/var/log/messages.也可以通过/etc/syslog.conf 配置文件重新指定。在启动klogd 的时候,可以通过指定-c 标志来改变终端的记录级。
四、oops
- oops 是内核告知用户有不幸发生的最常用的方式。oops 的产生有很多可能原因,其中包括内存访问越界或者非法的指令等。
1、ksymoops
如果使用的是模块, 还需要一些模块信息。ksymoops 通常会自行解析这些信息,调用后得到解码板的oops
ksymoops saved_ oops. txt
2、kallsyms
- 通过定义CONFIG_KALLS YMS 配置选项启用。该选项存放着内核镜像中相应函数地址的符号名称,所以内核可以打印解码好的跟踪线索
五、内核调试配置选项
内核开发( Kernel hacking)菜单项中,它们都依赖于CONFIG_DEBUG_KERNEL。。其中最有用的一个是sleep-inside-spinlock-checking (自旋锁内睡眠选项)。使用锁时睡眠是引发死锁的元凶。所以,包括正使用锁的时候调用,正使用锁的时候以阻塞方式请求分配内存和在引用单CPU 数据时睡眼在内,各种潜在的bug 都能够被探测到。
六、引发bug 并打印信息
最常用的两个是BUG() 和BUG_ON()。当披调用的时候,它们会引发oops ,导致栓的回溯和错误信息的打印可以把这些调用当做断言使用,想要断言某种情况不该发生:
if (bad_thing)
BUG();
或者使用更好的形式:
BUG_ON (bad_thing);
多数内核开发者相信BUG_ON()比BUG()更清晰、更可读, 而且BUG_ON()会将其声明作为一个语句放入unlikely()中。
可以用panic()引发更严重的错误。调用panic()不但会打印错误消息,而且还会挂起整个系统。显然,只应该在最糟糕的情况下使用它
if (terrible_thing)
panic ( ” terrible thing is %ld\n ”, terrible_thing);
七、内核调试器的传奇
1、gdb
- 可以使用标准的GNU 调试器对正在运行的内核进行查看。针对内核启动调试器的方站与针对进程的方栋大致相同:
gdb vml inux /proc/kcore
【其中vmlinux 文件是未经压缩的内核映像,不是压缩过的zlmage 或bzlmage,它存放在源代码树的根目录上。】
- /proc/kcore 作为一个参数选项,是作为core 文件来用的,通过它能够访问到内核驻留的高端内存。只有超级用户才能读取此文件的数据。可以使用gdb 的所有命令来获取信息。如果编译内核的时候使用了-g 参数(在内核的Makefile 文件的CFLAGS 变量中加入-g),gdb 还可以提供更多的信息。
2、kgdb
- kgdb 是一个补丁,它可以让我们在远端主机上通过串口利用gdb 的所有功能对内核进行调试。这需要两台计算机:第一台运行带有kgdb补丁的内核,第二台通过行线(不通过modem,直接连接两台机器的电缆)使用gdb对第一台进行调试。
八、使用Git 进行二分搜索
一开始,你得告诉Git 你要进行二分搜索:
$ git bisect start
然后再为Git 提供一个出现问题的最早内核版本:
$ git bisect bad <revision>
如果当前的内核版本就是引发bug的罪魁祸首,那么就不必提供内核版本:
$ git bisect bad
然后,还得为Git 提供一个最新的可正常运行的内核版本:
$ git bisect good v2.6.28
如果这个版本一切正常,可以运行下面的命令:
$ git bisect good
如果这个版本运行有异常一一也就是说,如果证明这个给定的内核版本有bug,可以运行:
$ git bisect bad
如果你已经知道引发bug 的源(比如, x86 机型的启动代码),你可以指定git仅仅在与错模相关的目录列表中去二分搜索提交的补丁。
$ git bisect start - arch/x86
《Linux内核设计与实现》 第十八章学习笔记的更多相关文章
- Linux内核设计与实现 第十八章
1. 内核调试的难点 重现bug困难 调试风险比较大 定位bug的初始版本困难 2. 内核调试的工具和方法 2.1 输出 LOG 输出LOG不光是内核调试, 即使是在用户态程序的调试中, 也是经常使用 ...
- Linux内核设计与实现第十周读书笔记
第十七章 设备与模块 关于设备驱动与设备管理,我们讨论四种内核成分. 设备类型 模块 内核对象 sysfs 17.1设备类型 在Linux以及所有Unix系统中,设备被分为以下三种类型: 块设备,块设 ...
- 《Linux内核设计与实现》Chapter 18 读书笔记
<Linux内核设计与实现>Chapter 18 读书笔记 一.准备开始 一个bug 一个藏匿bug的内核版本 知道这个bug最早出现在哪个内核版本中. 相关内核代码的知识和运气 想要成功 ...
- 《Linux内核设计与实现》Chapter 3 读书笔记
<Linux内核设计与实现>Chapter 3 读书笔记 进程管理是所有操作系统的心脏所在. 一.进程 1.进程就是处于执行期的程序以及它所包含的资源的总称. 2.线程是在进程中活动的对象 ...
- 《Linux内核设计与实现》第四周读书笔记——第五章
<Linux内核设计与实现>第四周读书笔记--第五章 20135301张忻 估算学习时间:共1.5小时 读书:1.0 代码:0 作业:0 博客:0.5 实际学习时间:共2.0小时 读书:1 ...
- 《Linux内核设计与实现》Chapter 1 读书笔记
<Linux内核设计与实现>Chapter 1 读书笔记 一.Unix的特点 Unix从Multics中产生,是一个强大.健壮和稳定的操作系统. 特点 1.很简洁 2.在Unix系统中,所 ...
- 《Linux内核设计与实现》Chapter 2 读书笔记
<Linux内核设计与实现>Chapter 2 读书笔记 一.获取内核源码 1.使用Git 我们曾经在以前的学习中使用过Git方法 $ git clone git://git.kernel ...
- 《Linux内核设计与实现》Chapter 5 读书笔记
<Linux内核设计与实现>Chapter 5 读书笔记 在现代操作系统中,内核提供了用户进程与内核进行交互的一组接口,这些接口的作用是: 使应用程序受限地访问硬件设备 提供创建新进程与已 ...
- LINUX内核设计与实现第三周读书笔记
LINUX内核设计与实现第三周读书笔记 第一章 LINUX内核简介 1.1 Unix的历史 1969年的夏天,贝尔实验室的程序员们在一台PDR-7型机上实现了Unix这个全新的操作系统. 1973年, ...
- 《Linux内核设计与实现》第一二章笔记
第一章 linux内核简介 每个处理器在任何时间点上的活动必然概括为下列三者: 运行于用户空间,执行用户进程 运行于内核空间,处于进程上下文,代表某个特定的进程执行 运行于内核空间,处于中断上下文,与 ...
随机推荐
- Tribonacci UVA - 12470 (简单的斐波拉契数列)(矩阵快速幂)
题意:a1=0;a2=1;a3=2; a(n)=a(n-1)+a(n-2)+a(n-3); 求a(n) 思路:矩阵快速幂 #include<cstdio> #include<cst ...
- 20145203盖泽双 《网络对抗技术》实践八:Web基础
20145203盖泽双 <网络对抗技术>实践八:Web基础 1.实践目标 (1)编写Web前端--含有表单的HTML代码. (2)编写Web前端--javascipt验证用户名.密码的代码 ...
- go标准库的学习-database/sql/driver
参考:https://studygolang.com/pkgdoc 1>导入方式: import "database/sql/driver" driver包定义了应被数据库驱 ...
- rac添加新节点的步骤与方法(官方步骤与自我测试)
Extending the Oracle Grid Infrastructure Home to the New NodeNow that the new node has been configur ...
- 剑指offer从上往下打印二叉树 、leetcode102. Binary Tree Level Order Traversal(即剑指把二叉树打印成多行、层序打印)、107. Binary Tree Level Order Traversal II 、103. Binary Tree Zigzag Level Order Traversal(剑指之字型打印)
从上往下打印二叉树这个是不分行的,用一个队列就可以实现 class Solution { public: vector<int> PrintFromTopToBottom(TreeNode ...
- [转]系统架构演变--集中式架构-垂直拆分-分布式服务-SOA(服务治理)-微服务
一.系统架构演变 1.1. 集中式架构 当网站流量很小时,只需一个应用,将所有功能都部署在一起,以减少部署节点和成本.此时,用于简化增删改查工作量的数据访问框架(ORM)是影响项目开发的关键. 存在的 ...
- MATLAB——神经网络pureline激活函数
- Wi-Fi无线控制器开发例程(基础篇)
动手来做自己的WIFI远程控制插座吧! 如果感觉视频不容易入门可以看这里 https://www.cnblogs.com/yangfengwu/p/10100152.html WIFI远程控制器系统方 ...
- 4-(基础入门篇)学会刷Wi-Fi模块固件(刷AT指令固件)
http://www.cnblogs.com/yangfengwu/p/8965054.html 基础教程源码链接如果失效,请在淘宝介绍中下载,由于链接很容易失效,如果失效请联系卖家,谢谢 https ...
- 8-51单片机ESP8266学习-AT指令(单片机采集温湿度数据通过8266发送给C#TCP客户端显示)
http://www.cnblogs.com/yangfengwu/p/8785516.html 先写单片机端的程序 先把源码和资料链接放到这里 链接: https://pan.baidu.com/s ...