20135302魏静静——课本18章学习笔记

第十八章 调试

一、内核中的bug

内核bug的原因可能有:

- 错误代码
- 同步时发生的错误,例如共享变量锁定不当
- 错误的管理硬件
- ……

内核bug发作的症状可能有:

- 降低所有程序的运行性能
- 毁坏数据
- 使得系统处于死锁状态
- ……

内核开发比起用户开发要多考虑一些独特的问题,比如:

- 定时限制
- 竞争条件
- ……
原因是允许多个线程在内核中同时运行。

二、通过打印来调试

1. 健壮性

  • 弹性极佳的函数:任何时候、任何地方都能调用它

    • 可以在中断上下文和进程上下文中被调用
    • 可以在任何持有锁时被调用
    • 可以在多处理器上同时被调用
  • 除非再启动过程中的初期就要在终端上输出

2. 日志等级

  • printk()printf()在使用上最主要的区别就是前者可以指定一个日志级别。内核通过这个级别来判断是否在终端上打印消息。
  • 内核把级别比某个特定值低的所有消息显示在终端上。
  • 如果没有指定一个记录等级,函数会选用默认的DEFAULT_MASSAGE_LOGLEVEL
  • 内核会把这些记录等级转化,n指等级,从0-7,对应表中从上到下,数字越小越重要。
           0   KERN_EMERG  最重要
            7   KERN_DEBUG  最不重要
  • 调试信息, 有两种赋予记录等级的方法:
      • 保持终端的默认记录等级不变,给所有调试信息KERN_CRIT或更低的等级。
      • 给所有调试信息KERN_DEBUG等级,调整终端的默认记录等级。
  • printk的输出日志级别如下:
等级 描述
KERN_ EMERG 一个紧急情况
KERN_ ALERT 一个需要立即被注意到的错误
KERN_ CRIT 一个临界情况
KERN_ ERR 一个错误
KERN_ WARNING 一个警告
KERN_ NOTICE 一个普通的, 不过也有可能需要注意的情况
KERN_ INFO 一条非正式的消息
KERN_ DEBUG 一条调试信息--一般是冗余信息

3. 缓冲区

  1. 内核消息都被记录在环形队列中,以队列方式进行读写;大小可以通过设置CONFIGLOGBUF_SHIFT进行调整
  2. 在单处理器上,该缓冲区大小默认为16KB,也就是说,超过的消息将覆盖旧消息
  3. 优势:
    1. 读写同步问题容易解决
    2. 记录的维护更加方便

4. 相关进程

  1. 用户空间的守护进程——klogd从记录缓冲区中读取内核信息,再通过syslogd守护进程将它们保存在系统日志文件中

    1. klogd会阻塞知道==直到有新的内核消息可供读出。被唤醒之后,它会读出新的内核消息并进行处理(默认情况下,就是传递给syslogd);
    2. syslogd会将所有接收到的消息添加到(默认情况下是messages)文件中

三、oops

oops是内核告知用户有不幸发生的最常用的方式
内核很难自我修复,也不能将自己杀死,只能发布oops,过程包括:

- 向终端上输出错误消息
- 输出寄存器中保存的信息
- 输出可供跟踪的回溯线索

通常发送完oops之后,内核会处于一种不稳定状态。

关于oops发生的时机:

  1. 发生在中断上下文:内核无法继续,会陷入混乱,导致系统死机
  2. 发生在idle进程或init进程(0号进程和1号进程),同上
  3. 发生在其他进程运行时,内核会杀死该进程并尝试着继续执行

内和调试配置项:

  1. 配置项:CONFIGDEBUGKERNEL
  2. 选项 之 sleep-inside-spinlockchecking(自旋锁内睡眠选项)——正在使用自旋锁或者禁止抢占的代码进行的是原子操作,不可更改
  3. 探测范围:
    • 正在使用锁的时候调用schedule();
    • 正使用锁的时候以阻塞方式请求分配内存;
    • 引用单CPU数据时睡眠

引发bug并打印信息:

  1. 利用BUG()以及BUG_ON()(因为大多数体系结构都把这两个函数定义成某种非法操作,可以触发oops)

    • 当做断言或者条件语句
  2. 调用panic()函数会在打印错误信息的同时挂起系统
    • panic("terrible thing",terrible_thing);
  3. 调用dump_stack(),只在终端上打印寄存器上下文及函数的跟踪线索

系统请求键

  1. 配置项:CONFIGMAGICSYSR配置选项来启动;此外,通过/proc/sys/kernel/sysrq标记该特性的开关
  2. 优点:无论内核处于什么状态,都可以通过特殊的组合键跟内核进行通信
  3. 常见的命令
    • SysRq-b:重启设备
    • SysRq-o:关闭机器
    • SysRq-u:卸载所有的文件系统
    • SysRq-s:把所有已安装的文件系统都刷新到磁盘

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

  1. 回溯线索:显示了导致错误发生的函数调用链。
  • 寄存器上下文信息也很有用,比如帮助冲进引发问题的现场
    • ksymoops

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

           kysmoop saved_oops.txt
    • kallsyms

现在的版本中不需要使用sysmoops这个工具,因为可能会发生很多问题,新版本中引入了kallsyms疼,可以通过定义CONFIG_KALLSYMS配置选项启用。

四、内核调试器

1.gdb

可以使用标准的GNU调试器对正在运行的内核进行查看。
针对内核启动调试器的方法与针对进程的方法大致相同:

gdb vmlinux /proc/kcore

vmlinx:未经压缩的内核映像,区别于zImage或bImage,它存放于源代码树的根目录上。
/proc/kcore作为一个参数选项,是作为core文件来用的,通过它能够访问到内核驻留的高端内存。只有超级用户才能读取此文件的数据

可以使用gdb的所有命令来获取信息。例如:

打印一个变量的值:
p global_variable

反汇编一个函数:
disassemble function

-g参数还可以提供更多的信息。

局限性:

  1. 没有办法修改内核数据
  2. 不能单步执行内核代码

2.kgdb

是一个补丁 ,可以让我们在远程主机上通过串口利用gdb的所有功能对内核进行调试。
需要两台计算机:仪态运行带有kgdb补丁的内核,第二胎通过串行线使用gdb对第一台进行调试。
通过kgdb,gdb的所有功能都能使用:

- 读取和修改变量值
- 设置断点
- 设置关注变量
- 单步执行

五、探测系统

1.使用uid作为选择条件

一般情况下,加入特性时,只要保留原有的算法而把新算法加入到其他位置上,基本就能保证安全。

可以把用户id(UID)作为选择条件来实现这种功能:
通过某种选择条件,安排到底执行哪种算法。
例如:

if (current-> uid !=7777) {
    /* 老算法…… */
} else {
    /* 新算法…… */
}

即,除了uid=7777的用户以外,其他所有的用户都是用的老算法,所以这个7777用户可以专门用来测试新算法。

2.使用条件变量

如果代码与进程无关,或者希望有一个针对所有情况都能使用的机制来控制某个特性,可以使用条件变量
这种方式比使用UID更简单,只需要创建一个全局变量作为一个条件选择开关:

  • 如果该变量为0,就使用某一个分支上的代码;
  • 否则,选择另外一个分支。

操控方式:某种接口,或者调试器。

3.使用统计量

这种方法常用于使用者需要掌握某个特定事件的发生规律的时候。
方法是创建统计量,并提供某种机制访问其统计结果。

4.重复频率限制

当系统的调试信息过多的时候,有两种方式可以防止这类问题发生:

  • 重复频率限制
  • 发生次数限制
时间: 2024-10-08 00:48:59

20135302魏静静——课本18章学习笔记的相关文章

20135302魏静静——课本1-2章学习笔记

第一章 Linux内核简介 一.Unix Unix是一个强大.健壮和稳定的操作系统. Unix——支持抢占式多任务.多线程.虚拟内存.换页.动态链接和TCP/IP网络. 二.操作系统和内核简介 操作系统是指在整个系统中负责完成最基本功能和系统管理的那些部分. 内核独立于普通应用程序,一般处于系统态,拥有受保护的内存空间和访问硬件设备的所有权限.这种系统态和被保护起来的内存空间,统称为内核空间.在系统中运行的应用程序通过系统调用来与内核通信. 应用程序完成其工作的基本行为方式是: 应用程序通过系统

20135302魏静静——课本5章学习笔记

第五章 系统调用 5.1 与内核通信 中间层 作用三个:1.为用户空间提供一种硬件的抽象接口:2.保证系统稳定和安全:3.除异常和陷入,是内核唯一的合法入口. 5.2 API.POSIX和C库 API定义了应用程序使用的编程接口(可实现系统调用). API.POSIX.C库与系统调用之间关系. 5.3 系统调用——syscall 5.3.1 系统调用号 当用户空间的进程执行一个系统调用,就用系统调用号指明到底执行哪个系统调用. sys_ni_syscall():错误号,负责“填补空缺”,返回-E

20135302魏静静——课本第4章学习笔记

第4章   进程调度 调度:调度是一个平衡的过程.一方面,它要保证各个运行的进程能够最大限度的使用CP:另一方面,保证各个进程能公平的使用CPU. 调度功能:决定哪个进程运行以及进程运行多长时间. 调度实现原理:与进程的优先级有关 Linux上调度实现的方法:O(1)的调度算法 调度相关的系统调用 4.1多任务   多任务系统可以划分为两类:非抢占式多任务( cooperative multitasking )和抢占式多任务(preemptive multitasking).像所 有Unix 的

20135302魏静静——课本第17章学习笔记

第17章   模块与设备 设备类型:在所有 Unix 系统中为了统一普通设备的操作所采用的分类. 模块: Linux 内核中用于按需加载和卸载目标码的机制. 内核对象:内核数据结构中支持面向对象的简单操作,还支持维护对象之间的父子关系. sysfs :表示系统中设备树的一个文件系统. 1. 设备类型 三种类型 块设备 字符设备 网络设备 2. 模块 1. Hello,World 模块的所有初始化函数必须符合形式:int my _ init (void); 退出函数必须符合形式:void my_e

20135302魏静静——课本第3章学习笔记

第三章   进程管理 本章主要内容: 进程和线程 进程的任务结构 进程和线程的创建 进程的终止 1. 进程和线程 进程:进程就是处于执行期的程序,实际上,进程就是正在执行的程序代码的实时结果: 线程:执行线程,简称线程,是进程中活动的对象(每个线程拥有独立的程序计数器.进程栈.和一组进程寄存器),内核调度的对象是线程,不是进程 进程提供2种虚拟机制:虚拟处理器和虚拟内存 每个进程有独立的虚拟处理器和虚拟内存, 每个线程有独立的虚拟处理器,同一个进程内的线程有可能会共享虚拟内存. 内核中进程的信息

scala编程第18章学习笔记——有状态的对象

银行账号的简化实现: scala> class BankAccount{ | private var bal: Int = 0 | def balance: Int = bal | def deposit(amount: Int) { | require(amount > 0) | bal += amount | } | | def withdraw(amount: Int): Boolean = | if (amount > bal) false | else{ | bal -= am

20135302魏静静——Linux课程期中总结

Linux期中总结 Linux课程第一周实验及总结:[http://www.cnblogs.com/20135302wei/p/5218607.html] 冯诺依曼体系结构的核心思想是存储程序计算机.在计算机中有两种指令,一是用户指令,一是系统调用. 当用户使用计算机时,计算机根据其汇编的指令一步步运行,当使用系统调用完后,再返回用户模式,保证系统的稳定. 程序中执行call的堆栈变化 汇编基础 通用寄存器 16位  32位 AX    eax 累加器BX    ebx 基址寄存器CX    e

【tapestry3笔记】--tapestry 初探,《 tapestry in action 》第一章学习笔记

由于要维护一个项目,要用到tapestry3这个老框架,虽然这个框架很老,但是在我看来ta的思想还是很先进的---面向组件编程. 由于网上资料少的可怜,辛苦找了很久终于找到一本名为<tapestry in action>的工具书,以下学习笔记均以此书为参考. 正文---tapestry初探 tapestry in action 第一章学习笔记 tapestry是一款以组件为核心的开发框架,组件就向一个黑盒子,我们无需关系组件是如何实现的,只需合理使用即可.这有点像jquery的插件,我们无需关

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

<Linux内核设计与实现>第一.二章学习笔记 姓名:王玮怡  学号:20135116 第一章 Linux内核简介 一.关于Unix ——一个支持抢占式多任务.多线程.虚拟内存.换页.动态链接和TCP/IP网络的现代化操作系统 1.主要发展过程   1969年,贝尔实验室的程序员们设计了一个文件系统原型,最终发展演化成了Unix 1971年,Unix被移植到PDP-11型机中 1973年,整个Unix系统使用C语言进行重写,为后来Unix系统的广泛移植铺平了道路 Unix第六版(V6)被贝尔实