Linux内核读书笔记第三周 调试
内核调试的难点在于它不能像用户态程序调试那样打断点,随时暂停查看各个变量的状态。
也不能像用户态程序那样崩溃后迅速的重启,恢复初始状态。
用户态程序和内核交互,用户态程序的各种状态,错误等可以由内核来捕获并显示。
而内核是直接和硬件交互的,内核出错之后整个系统就无法正常运行了,所以要想熟练的进行内核调试,
首先要熟悉内核已经给我们提供的工具,然后实实在在的去做一些内核功能的开发,在开发的过程中不断熟悉内核代码,增加内核调试的经验。
主要内容:
内核调试的难点
内核调试的工具和方法
总结
- 内核调试的难点
内核调试的难点大致有以下几个:
重现bug困难 - 如果能够重现一个bug, 相当于成功了一半. (特别是有些bug和硬件相关, 执行几百万次之后才有一次错误)
调试风险比较大 - 稍有不慎, 即造成系统崩溃
定位bug的初始版本困难 - 内核版本更新很快, 很难确定bug是在那个版本开始出现的
- 内核调试的工具和方法
内核调试虽然困难, 但同时也极具挑战性, 如果能够解决一个困扰大家多时的内核bug, 那将会给自己带来极大的成就感. :)
而且, 随着内核的不断发展, 内核调试的手段和方法也在不断进步, 下面是书中提到的一些常用的调试手段.
2.1 输出 LOG
输出LOG不光是内核调试, 即使是在用户态程序的调试中, 也是经常使用的一个调试手段.
通过在可疑的代码周围加上一些LOG输出, 可以准确的了解bug发生前后的一些重要信息.
2.1.1 LOG等级
linux内核中输出LOG的函数是 printk (语法和printf几乎雷同, 唯一的区别是printk可以指定日志级别)
printk之所以好用, 就在与它随时都可以被调用, 没有任何限制条件.
printk的输出日志级别如下:
等级
描述
KERN_EMERG 一个紧急情况
KERN_ALERT 一个需要立即被注意到的错误
KERN_CRIT 一个临界情况
KERN_ERR 一个错误
KERN_WARNING 一个警告
KERN_NOTICE 一个普通的, 不过也有可能需要注意的情况
KERN_INFO 一条非正式的消息
KERN_DEBUG 一条调试信息--一般是冗余信息
2.1.2 LOG记录
标准linux系统上, printk 输出log之后, 由用户空间的守护进程klogd从缓冲区中读取内核消息, 然后再通过syslogd守护进程将它们保存在系统日志文件中.
syslogd 将接受到的所有内核消息添加到一个文件中, 该文件默认为: /var/log/dmesg (系统Centos6.4 x86_64)
PS. 上篇博客中的内核模块的输出LOG, 都可以在 /var/log/dmesg 中看到
2.2 oops
oopss是个拟声词, 类似 "哎哟" 的意思. 它是内核通知用户有不幸发生的最常用方式.
触发一个oops很简单, 其实只要在上篇博客中的那些内核模块示例中随便找一个, 里面加上一段给未初始化的指针赋值的代码, 就能触发一个oops
oops中包含错误发生时的一些重要信息(比如, 寄存器上下文和回溯线索), 对调试bug很有帮助!
调试内核时, 还可以开启内核编译参数中的各种和内核调试相关的选项, 那样还可以给我们提供内核崩溃时的一些额外信息.
2.3 主动触发bug
调试中有时将某些情况下标记为bug, 执行到这些情况时, 提供断言并输出信息.
BUG 和 BUG_ON 就是2个可以主动触发oops的内核调用.
在不应该被执行到的地方使用 BUG 或者 BUG_ON 来捕获.
2.4 神奇的系统请求键
这个系统请求键之所以神奇, 在于它可以在一个快挂了的系统上输出一些有用的信息.
这个按键一般就是标准键盘上的 [SysRq] 键 (就在 F12 键右边, 其实就是windows中截整个屏幕的按键)
单独按那个键相当于截屏, 按住 ALT + [SysRq] = [SysRq]的功能
启用这个键的功能有2个方法:
开启内核编译选项 : CONFIG_MAGIC_SYSRQ
动态启用: echo 1 > /proc/sys/kernel/sysrq
支持 SysRq 的命令如下: (注意要在控制台界面下使用这个键, 比如通过 ALT+CTRL+F2 进入一个控制台界面)
主要命令
描述
SysRq-b 重新启动机器
SysRq-e 向init以外的所有进程发送SIGTERM信号
SysRq-h 在控制台显示SysRq的帮助信息
SysRq-i 向init以外的所有进程发送SIGKILL信号
SysRq-k 安全访问键:杀死这个控制台上的所有程序
SysRq-l 向包括init的所有进程发送SIGKILL信号
SysRq-m 把内存信息输出到控制台
SysRq-o 关闭机器
SysRq-p 把寄存器信息输出到控制台
SysRq-r 关闭键盘原始模式
SysRq-s 把所有已安装文件系统都刷新到磁盘
SysRq-t 把任务信息输出到控制台
SysRq-u 卸载所有已加载文件系统
2.5 内核调试器 gdb和kgdb
linux内核的调试器可以使用 gdb或者kgdb, 配置比较麻烦, 准备实际用调试的时候再去试试效果如何..
2.6 探测系统
下面一些方法是在修改内核后, 用来试探内核反应的小技巧.
2.6.1 用UID控制内核执行
比如在内核中加入了新的特性, 为了测试特性, 可以用UID来控制内核是否执行新特性.
2.6.2 用条件变量控制内核执行
也可以设置一些条件变量来控制内核是否执行某段代码.
条件变量可以像上篇博客中那样, 设置在 sys 文件系统的某个文件中. 当文件中的值变化时, 通知内核执行相应的代码.
2.6.3 使用统计量观察内核执行某段代码的频率
实现思路就是在内核中的设置一个全局变量, 比如 my_count, 当内核执行到某段代码时, 给 my_count + 1 就行.
同时还要将 my_count 打印出来(可以用printk), 便于随时查看它的值.
2.6.4 控制内核执行某段代码的频率
有时侯, 我们需要在内核发生错误时打印错误相关的信息, 如果这个错误不会导致内核崩溃, 并且这个错误每秒会发生几百次甚至更多.
那么, 用printk输出的信息会非常多, 给系统造成额外的负担.
这时, 我们就需要想办法控制错误输出的频率, 有2种方法:
方法1: 隔一段时间才输出一次错误
方法2: 输出 N 次之后, 不再输出(N是正整数)
2.7 二分法查找bug发生的最初内核版本
在内核发生了bug之后, 如果能够知道是bug从哪个内核版本开始出现的, 那对修正这个bug会有很大的帮助.
由于内核代码非常庞大, 即使用二分查找法, 手工去找哪个版本开始出现bug的话, 仍然是非常耗时和繁琐的.
Linux内核读书笔记第三周 调试的更多相关文章
- 20135316王剑桥Linux内核学习笔记第三周
		20135316王剑桥 <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC 1000029000 三个法宝:存储程序计算机.函数调 ... 
- Linux内核读书笔记第六周
		主要内容: 什么是调度 调度实现原理 Linux上调度实现的方法 调度相关的系统调用 什么是调度 现在的操作系统都是多任务的,为了能让更多的任务能同时在系统上更好的运行,需要一个管理程序来管理计算机上 ... 
- Linux内核读书笔记第五周链接
		1.临界区(critical regions)就是访问和操作共享数据的代码段.多个执行线程并发访问同一个资源通常是不安全的,为了避免在临界区中并发访问,编程者必须保证这些代码 原子地执行.也就是说,代 ... 
- 《Linux内核分析》第三周学习笔记
		<Linux内核分析>第三周学习笔记 构造一个简单的Linux系统MenuOS 郭垚 原创作品转载请注明出处 <Linux内核分析>MOOC课程http://mooc.stud ... 
- 《Linux内核分析》第三周学习报告
		<Linux内核分析>第三周学习报告 ——构造一个简单的Linux系统MenuOS 姓名:王玮怡 学号:201351 ... 
- 读书笔记第三周 人月神话 刘鼎乾 PB16070837
		读书笔记第三周:人月神话 这本书主要讲述了如何管理一个软件开发团队的问题,其中如何提高团队的效率可以说是本书的重点之一了.感觉这本书地中文版翻译得比较晦涩,很多表达比较模糊,看起来有些吃力,因此下 ... 
- 《Linux内核分析》第三周笔记 构造一个简单的Linux系统MenuOS
		构造一个简单的Linux系统MenuOS 一.linux内核源代码简介 三大法宝(存储程序计算机.函数调用堆栈.中断)和两把宝剑(中断上下文的切换:保存现场和恢复现场.进程上下文的切换) 1.在lin ... 
- Linux内核读书笔记第二周
		什么是系统调用 简单来说,系统调用就是用户程序和硬件设备之间的桥梁.用户程序在需要的时候,通过系统调用来使用硬件设备. 系统调用的存在,有以下重要的意义: 1)用户程序通过系统调用来使用硬件,而不用关 ... 
- 《Linux内核分析》第三周学习小结 构造一个简单的Linux系统OS
		郝智宇 无转载 <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 第三周 构造一个简单的Linux系统Me ... 
随机推荐
- python之字符串的常用操作(转)
			1. 字符串的操作 字符串的连接操作 符号: + 格式:str1 + str2 例如:str1 = 'I Love' str2 = 'You!' print(str1 + str2) >> ... 
- Activiti工作流搭建---初始化数据库
			Activiti介绍 Activiti5是由Alfresco软件在2010年5月17日发布的业务流程管理(BPM)框架,它是覆盖了业务流程管理.工作流.服务协作等领域的一个开源的.灵活的.易扩展的可执 ... 
- bzoj5093:[Lydsy1711月赛]图的价值
			题目 首先考虑到这是一张有标号的图,每一个点的地位是相等的,因此我们只需要求出一个点的价值和乘上\(n\)就好了 考虑一个点有多少种情况下度数为\(i\) 显然我们可以让除了这个点的剩下的\(n-1\ ... 
- 项目Alpha冲刺 5
			作业描述 课程: 软件工程1916|W(福州大学) 作业要求: 项目Alpha冲刺(团队) 团队名称: 火鸡堂 作业目标: 介绍第五天冲刺的项目进展.问题困难和心得体会 1.团队信息 队名:火鸡堂 队 ... 
- MySql常用命令集Mysql常用命令showdatabases;显示数据库createdatab
			MySql 常用命令集 Mysql常用命令 show databases; 显示数据库 create database name; 创建数据库 use databasename; 选择数据库 drop ... 
- 通过SQL Server 2008 访问Oracle 10g
			原文地址:http://www.cnblogs.com/gnielee/archive/2010/09/07/access-oracle-from-sqlserver.html 之前写过一篇关于SQL ... 
- kubelet 初始化过程
			kubelet 初始化过程 . kubelet 启动 . kubelet认为,它并没有有一个kubeconfig文件 . kubelet搜索并查找bootstrap-kubeconfig文件 . ku ... 
- go标准库的学习-crypto/md5
			参考:https://studygolang.com/pkgdoc 导入方式: import "crypto/md5" md5包实现了MD5哈希算法,参见RFC 1321. Con ... 
- 蒟蒻qxt的sd'日常
			emm... 今天刷了一道水题 居然 死循环了 真的是水题啊 顿时自闭 (救救孩子吧) 结果 bug是 我把for循环中的i的值改变了 使得i的值一直都不会达到他的边界值 于是就死循环了 所以 要用到 ... 
- 个人向 - vscode插件记录
			现在用的编译器的是vscode,本身这个编译器很小,很多功能都没有,需要自己下载一些插件来完善功能,不知不觉下载的插件也有三十多个了,感觉需要记录一下. tips:1. vscode插件的安装位置:’ ... 
