一、准备开始

1、一个确定的bug,但大部分bug通常都不是行为可靠且定义明确的。

2、一个藏匿bug的内核版本。

3、相关内核代码的知识和运气。

二、内核中的bug

1、bug的表象:

明白无误的错误代码,同步时发生的错误,错误地管理硬件,降低所有程序的运行性能,毁坏数据,使系统处于死锁状态。

2、引用空指针会导致产生一个oops,垃圾数据可能会导致系统崩溃。

三、通过打印来调试

1、printk()是内核的格式化打印函数,与C库提供的printf()函数功能基本相同。

2、printk()在任何时候、任何地方都能调用它。除了系统启动过程中,终端还没有初始化之前,在某些地方不能使用它。

early_printk()在启动过程的初期就具备在终端上打印的能力,但缺少可移植性。

3、printk()和printf()的最主要区别:

printk()可以指定一个日志级别,内核根据这个级别来判断是否在终端上打印消息。

内核同这个指定的记录等级和当前终端的记录等级console_loglevel来决定是不是向终端上打印。

如果你没有特别指定一个记录等级,函数会选用默认的DEFAULT_MESSAGE_LOGLEVEL。

内核将最重要的记录等级KERN_EMERG定为“<0>”,将无关紧要的记录等级KERN_DEBUG定为“<7>”。

例:

当编译预处理完成后,代码被编译成如下格式:

4、给调用的printk()赋记录等级的方法

(1)保持终端的默认记录等级不变,给所有调试信息KERN_CRIT或更低的等级。

(2)给所有调试信息KERN_DEBUG等级,而调整终端的默认记录等级。

5、内核消息都被保存在一个LOG_BUF_LEN大小的环形队列中。

该缓冲区大小可以在编译时通过设置CONFIG_LOG_BUF_SHIFT进行调整,在单处理器的系统上其默认值是16KB。

**使用环形队列的优劣**

6、用户空间的守护进程klogd从记录缓冲区中获取内核消息,再通过syslogd守护进程将它们保存在系统日志文件中。

四、OOPS

1、oops是内核告知用户有不幸发生的最常用的方式。

这个过程包括向终端上输出错误消息,输出寄存器中保存的信息并输出可供跟踪的回溯线索。

2、如果oops在中断上下文时发生,内核根本无法继续,它会陷入混乱,导致系统死机。

如果oops在idle进程(pid为0)或者init进程(pid为1)时发生,结果同样是系统陷入混乱。

3、oops中包含的重要信息:寄存器上下文和回溯线索。

回溯线索中的地址需要转化成有意义的符号名称:调用ksymoops命令,并且提供编译内核时产生的System.map;如果使用的是模块,还需要一些模块信息。

ksymoops saved_oops.txt

4、kallsyms特性,它可以通过定义CONFIG_KALLSYMS配置选项启用。

五、内核调试配置选项

原子操作:指那些能够不分隔执行的东西,在执行时不能中断否则就是完不成的代码。

六、引发bug并打印信息

1、一些内核调用可以用来方便标记bug,提供断言并输出信息。最常用的两个是BUG()和BUG_ON()。

当被调用的时候,会引发oops。可以把这些调用当做断言使用,想要断言某种情况不该发生:

BUG_ON()比BUG()更清晰、更可读,而且BUG_ON()会将其声明作为一个语句放入unlikely()中。

BUILD_BUG_ON()与BUG_ON()作用相同,仅在编译时调用。

可以用panic()引发更严重的错误:打印错误信息,挂起整个系统,但应该在最糟糕的情况下使用它。

七、神奇的系统请求键

1、神奇的系统请求键(Magic SysRq key),该功能可以通过定义CONFIG_MAGIC_SYSRQ配置选项来启用。当该功能被启用的时候,无论内核处于什么状态,都可以通过特殊的组合键跟内核进行通信。

2、除了配置选项外,还要通过一个sysctl用来标记该特性的开或关:

echo 1 > /proc/sys/kernel/sysrq

八、内核调试器的传奇

1、gdb

可以使用标准的GNU调试器对正在运行的内核进行查看:gdb vmlinux /proc/kcore

其中vmlinux文件时未经压缩的内核映像,它存放在源代码树的根目录上。

/proc/kcore作为一个参数选项,是作为core文件来用的,通过它能够访问到内核驻留的高端内存。

如果编译内核的时候使用-g参数,gdb还可以提供更多的信息。

2、kgdb

是一个补丁,它可以让我们在远端主机上通过串口利用gdb的所有功能对内核进行调试。

九、探测系统

1、用UID作为选择条件

2、使用条件变量

如果代码与进程无关,或者希望有一个针对所有情况都能使用的机制来控制某个特性,可以使用条件变量。

3、使用统计量

需要掌握某个特定事件的发生规律或需要比较多个事件并从中得出规律。

4、重复频率限制:某种事件发生的非常频繁,而又需要观察它的整体进展情况。

发生次数限制:确认在特定情况下某段代码确实被执行了。

不管哪种情况,用到的变量都应该是静态的static,并且应该限制在函数的局部范围以内,这样才能保证变量的值在经历多次函数调用后仍然能够保留下来。

十、用二分查找法找出引发罪恶的变更

一开始,需要一个可靠的可复制的错误,最好是系统一启动就能查证的bug。

接下来,需要一个能确保没问题的内核。

接下来,还需要一个肯定有问题的内核。

十一、使用Git进行二分搜索

一开始,告诉Git进行二分搜索:git bisect start。

如果这个版本一切正常,可以运行下面的命令:git bisect good。

如果证明这个给定的内核版本有bug,可以运行:git bisect bad。

如果你已经知道引发bug的源(比如,x86机型的启动代码),你可以指定git仅仅在与错误相关的目录列表中去二分搜索提交的补丁:git bisect start - arch/x86

总结:

这一章主要介绍了系统调用的知识,与MOOC中的视频教学相辅相成,在许多细节上作了补充,尤其在如何增加一个新的系统调用上介绍的很详细。另外,编写规范的、最优化的、安全的系统调用所遵循的概念和内核接口规范也值得我们注意。

系统调用是利用了软中断的机制,由API、POSIX和C库协调工作。虽然系统调用使用起来非常方便,但仍要尽量避免每出现一种新的抽象就简单的加入一个新的系统调用,而新系统调用增添频率很低也反映出Linux是一个相对较为稳定并且功能已经较为完善的操作系统。

《Linux内核设计与实现》学习总结 Chap18的更多相关文章

  1. Linux内核设计第一周学习总结 计算机如何工作

    北京电子科技学院 20135310陈巧然 原创作品转载请注明出处 <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-100002 ...

  2. Linux内核设计第二周学习总结 完成一个简单的时间片轮转多道程序内核代码

    陈巧然 原创作品 转载请注明出处 <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 一.使用实验楼的虚拟机 ...

  3. Linux内核设计第四周学习总结 使用库函数API和C代码中嵌入汇编代码两种方式使用同一个系统调用

    陈巧然原创作品 转载请注明出处 <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 实验目的: 使用库函数A ...

  4. linux内核设计与实现学习笔记-模块

    模块 1.概念:  如果让LINUX Kernel单独运行在一个保护区域,那么LINUX Kernel就成为了“单内核”.    LINUX Kernel是组件模式的,所谓组件模式是指:LINUX K ...

  5. 《Linux内核设计与实现》课本第五章学习笔记——20135203齐岳

    <Linux内核设计与实现>课本第五章学习笔记 By20135203齐岳 与内核通信 用户空间进程和硬件设备之间通过系统调用来交互,其主要作用有三个. 为用户空间提供了硬件的抽象接口. 保 ...

  6. 《Linux内核设计与实现》课本第一章&第二章学习笔记

    <Linux内核设计与实现>课本学习笔记 By20135203齐岳 一.Linux内核简介 Unix内核的特点 Unix很简洁,所提供的系统调用都有很明确的设计目的. Unix中一切皆文件 ...

  7. 《Linux内核设计与实现》 第一二章学习笔记

    <Linux内核设计与实现> 第一二章学习笔记 第一章 Linux内核简介 1.1 Unix的历史 Unix的特点 Unix很简洁,所提供的系统调用都有很明确的设计目的. Unix中一切皆 ...

  8. 《Linux内核设计与实现》第四章学习笔记

    <Linux内核设计与实现>第四章学习笔记           ——进程调度 姓名:王玮怡  学号:20135116 一.多任务 1.多任务操作系统的含义 多任务操作系统就是能同时并发地交 ...

  9. 《Linux内核设计与实现》第五章学习笔记

    <Linux内核设计与实现>第五章学习笔记 姓名:王玮怡  学号:20135116 一.与内核通信     在Linux中,系统调用是用户空间访问内核的唯一手段:除异常和陷入外,它们是内核 ...

  10. 《Linux内核设计与实现》第四章学习笔记——进程调度

                                                                        <Linux内核设计与实现>第四章学习笔记——进程调 ...

随机推荐

  1. OTRS

    更新OTRS root@localhost密码: sudo -u otrs /opt/otrs/bin/otrs.Console.pl Admin::User::SetPassword root@lo ...

  2. CocoStuff—基于Deeplab训练数据的标定工具【三、标注工具的使用】

    一.说明 本文为系列博客第三篇,主要展示COCO-Stuff 10K标注工具的使用过程及效果. 本文叙述的步骤默认在完成系列文章[二]的一些下载数据集.生成超像素处理文件的步骤,如果过程中有提示缺少那 ...

  3. 搭建Harbor私有镜像仓库--v1.5.1

     搭建Harbor私有镜像仓库--v1.5.1 1.介绍 Docker容器应用的开发和运行离不开可靠的镜像管理,虽然Docker官方也提供了公共的镜像仓库,但是从安全和效率等方面考虑,部署我们私有环境 ...

  4. Java 的 java_home, path, classpath

    java_home: 指定 jdk 的安装目录. 第三方软件 Eclipse / Tomcat 在 java_home 指定的目录下查找安装好的 jdk. path: 配置 jdk 的安装目录.在命令 ...

  5. 设计与实现分离——面向接口编程(OO博客第三弹)

    如果说继承是面向对象程序设计中承前启后的特质,那么接口就是海纳百川的体现了.它们都是对数据和行为的抽象,都是对性质和关系的概括.只不过前者是纵向角度,而后者是横向角度罢了.今天呢,我想从设计+语法角度 ...

  6. cnblogs用户体验及建议

    一.是否提供了良好的体验给用户(同时提供价值)? 我觉得博客园还是给用户提供了良好的用户体验的,它可以从用户的角度考虑,用户在注册的时候,用户自己在设置用户名和密码的时候,如果与他人重复会有提示,而且 ...

  7. 1到N中“1”出现的次数

    题目:给定一个十进制的正整数,写下从1开始,到N的所有整数,然后数一下其中出现“1”的个数 思路:刚开始做的时候,是想从1到N进行遍历,其中每个数都出现1的个数加起来,最后得出结果,但是老师让我们找规 ...

  8. bata2

    目录 组员情况 组员1(组长):胡绪佩 组员2:胡青元 组员3:庄卉 组员4:家灿 组员5:凯琳 组员6:翟丹丹 组员7:何家伟 组员8:政演 组员9:黄鸿杰 组员10:刘一好 组员11:何宇恒 展示 ...

  9. 404 Note Found团队-项目UML设计

    目录 团队信息 分工选择 课上分工 课下分工 ToDolist alpha版本要做的事情 燃尽图 UML 用例图 状态图 活动图 类图 部署图 实例图 对象图 时序图 包图 通信图 贡献分评定 课上贡 ...

  10. Centos7 虚拟机复制后网卡问题 Job for network.service failed

    在运行“/etc/init.d/network restart”命令时,出现错误“Job for network.service failed. See 'systemctl status netwo ...