《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内核简介 每个处理器在任何时间点上的活动必然概括为下列三者: 运行于用户空间,执行用户进程 运行于内核空间,处于进程上下文,代表某个特定的进程执行 运行于内核空间,处于中断上下文,与 ...
随机推荐
- oracle+st_geometry
最近因为性能的原因开始关注通过oracle和st_geometry直接操作数据库来解决实际业务问题.主要还是用到了“使用 SQL 处理 ST_Geometry”.对此,ESRI给出的帮助文档中的解释如 ...
- JS获取本周、本季度、本月、上月的开始日期、结束日期
/** * 获取本周.本季度.本月.上月的开始日期.结束日期 */ var now = new Date(); //当前日期 var nowDayOfWeek = ...
- luogu P4515 [COCI2009-2010#6] XOR
luogu P4515 [COCI2009-2010#6] XOR 描述 坐标系下有若干个等腰直角三角形,且每个等腰直角三角形的直角顶点都在左下方,两腰与坐标轴平行.被奇数个三角形覆盖的面 积部分为灰 ...
- Docker部署HDFS
docker部署hadoop只是实验目的,每个服务都是通过手动部署,比如namenode, datanode, journalnode等.如果为了灵活的管理集群,而不使用官方封装好的自动化部署脚本,本 ...
- 20145236《网络攻防》Exp5 MSF基础应用
20145236<网络攻防>Exp5 MSF基础应用 一.基础问题回答 解释exploit,payload,encode是什么: exploit就是负责负载有用代码的交通工具,先通过exp ...
- node学习之cookie和session
c什么是cookie Cookie设计的初衷是 维持浏览器和服务端的状态.http是无状态的,服务端不能跟踪客户端的状态. 浏览器第一次向服务器发送请求,服务器会返回一个cookie给客户端浏览器,浏 ...
- 这款 WordPress商用插件 0day 漏洞满满,且已遭利用
Wordfence 安全研究员发布报告称,WordPress 商用插件 Total Donations 受多个 0day 漏洞的影响,且这些漏洞已遭利用. 这些严重的漏洞影响所有已知的 Total D ...
- spring 和spring cloud 组成
spring 顶级项目:Spring IO platform:用于系统部署,是可集成的,构建现代化应用的版本平台,具体来说当你使用maven dependency引入spring jar包时它就在工作 ...
- [01-01] 示例:用Java爬取新闻
1.分析url <空港双流>数字报刊,访问地址为:http://epaper.slnews.net.cn,现在为了抓取每篇新闻的网页内容. 在浏览器访问该链接后,发现链接出现了变化,看样子 ...
- Linux常用基础命令整理:关机命令、查看目录下文件命令等
Linux常用基础命令整理:关机命令.查看目录下文件命令等 整理了一些Linux常用基础命令,欢迎指正. 首先记住四个热键,学会这四个键,收益一辈子. Tab按键---命令补齐功能Ctrl+c按键-- ...