zoukankan      html  css  js  c++  java
  • 2013337朱荟潼 Linux第十八章读书笔记——调试

    第十八章 调试

    0.总结

    • oops
    • 内核的调试配置
    • 用Git进行二分搜索
    • bug总会有,简洁描述发给LKML

    1. 准备开始

    • 在用户级的程序里,bug表现比较直接;在内核中却不清晰。

    2. 内核中的bug

    • 多种多样、变化多端。
    • 引用空指针会产生一个oops;垃圾数据会导致系统崩溃。
    • 定时限制和竞争条件都允许多个线程在内核中同时运行产生的结果。

    3. 通过打印来调试

    3.1 健壮性

    • printk()函数任何时候地方都可以调用它。

    3.2 日志等级

    • printk()可以指定一个日志级别【与printf()最大区别】。

    • 内核判断是否在终端上打印消息的依据。

    • 指定一个记录级别的方式:

    • KERN_WARING和KERN_DEGUG是<linux/kernel.h>中的简单宏定义。

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

    • 默认级别:KERN_WARNING。

    • 按照自己想法赋予记录等级方法:

    3.3 记录缓冲区

    3.4 syslogd和klogd

    3.5 从printf()到printk()的转换

    • 错误中培养新习惯。

    4. oops

    • 内核告知用户有不幸发生的最常见方式。
    • 内核发布oops会向终端输出的内容:

    1.错误消息;
    2.寄存器中保存的信息;
    3.可供跟踪的回溯线索。
    
    • oops发生时间出现的状况:

    • oops包含信息:

    4.1 ksymoops

    • 将回溯线索中的地址转化成符号名称,调用ksymoops命令并提供System.map:

    ksymoops saved_oops.txt
    

    4.2 kallsyms

    • CONFIG_KALLSYMS 定义配置选项启用。
    • CONFIG_KALLSYMS_ALL 存放函数名称;存放所有符号名称。
    • CONFIG_KALLSYMS_EXTRA_PASS 引起内核构建中再次忽略内核的目标代码。

    5. 内核调试配置选项

    • 在内核配置编辑器的内核开发菜单项中,依赖CONFIG_DEBUG_KERNEL。

    6. 引发bug并打印信息

    • 常用BUG()和BUG_ON()。
    • 调用会引发oops

    7. 神奇的系统请求键

    • 通过定义CONFIG_MAGIC_SYSRQ配置选项来启用。
    • 内核可以通过特殊的组合键和内核进行通信。
    • sysctl来标记该特性的开或关。需要启用时:

    echo 1 > /proc/sys/kernel/sysrq
    

    8. 内核调试器的传奇

    8.1 gdb

    • 针对内核启动调试器的方法和对进程的方法大致相同:

    gdb vmlinux /proc/kcore
    vmlinux文件是未压缩的内核映像;
    /proc/kcore是一个参数选项,作为core文件来用,只有超级用户才能读取此文件的数据。
    
    • 打印一个变量的值:

    p global_variable
    
    • 反汇编一个函数:

    disassemble function
    
    • 局限性:

    不能修改内核数据;
    不能单步执行内核代码;
    不能加断点
    

    8.2 kgdb

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

    9. 探测系统

    9.1 用UID作为选择条件

    • 利用把用户id(UID)作为选择条件实现新算法加入:

    9.2 使用条件变量

    • 使用前提:

    代码与进程无关;
    希望有一个针对所有情况都能用的机制来控制某个特性。
    
    • 只需创建一个全局变量作为一个选择开关。

    9.3 使用统计量

    • 提供某种机制访问其统计结果。

    9.4 重复频率限制

    • 为了避免调试信息发生井喷,可以每隔几秒执行一次操作。

    10. 用二分法找出引发罪恶的变更

    11. 使用Git进行二分搜索

    $ git bisect start  ;进行二分搜索
    $ git bisect bad <revision>   ;引发提供一个出现问题的最高内核版本
    $ git bisect bad    ;若当前内核版本就是bug的元凶,那不必提供内核版本
    $ git bisect good v2.6.28    ;最新可正常运行的内核版本
    
    $ git bisect good    ;这个版本正常
    $ git bisect bad     ;这个版本有异常
    

    12. 当所有努力都失败时:社区

    • Linux内核邮件列表(LKML)
  • 相关阅读:
    C#数据结构与算法系列(十三):递归——迷宫问题
    C#数据结构与算法系列(十二):递归(Recursion)
    C#数据结构与算法系列(十一):中缀表达式转后缀表达式
    C#数据结构与算法系列(十):逆波兰计算器——逆波兰表达式(后缀表达式)
    Quartz.Net系列(八):Trigger之CalendarIntervalScheduleBuilder详解
    Quartz.Net系列(七):Trigger之SimpleScheduleBuilder详解
    C#数据结构与算法系列(九):栈实现综合计算器(中缀表达式)
    Redis系列(五):数据结构List双向链表源码解析和API实现
    Quartz.Net系列(六):Quartz五大构件Trigger之TriggerBuilder解析
    C#数据结构与算法系列(八):栈(Stack)
  • 原文地址:https://www.cnblogs.com/zzzz5/p/5330119.html
Copyright © 2011-2022 走看看