内核调试的一些配置
来源:互联网 发布:网络电视可以暂仃画面 编辑:程序博客网 时间:2024/06/16 00:07
学习编写驱动程序要构建安装自己的内核(标准主线内核)。最重要的原因之一是:内核开发者已经建立了多项用于调试的功能。但是由于这些功能会造成额外的输出,并导致能下降,因此发行版厂商通常会禁止发行版内核中的调试功能。
1 内核配置
为了实现内核调试,在内核配置上增加了几项:
Kernel hacking ---> [*] Magic SysRq key [*] Kernel debugging [*] Debug slab memory allocations [*] Spinlock and rw-lock debugging: basic checks [*] Spinlock debugging: sleep-inside-spinlock checking [*] Compile the kernel with debug info Device Drivers ---> Generic Driver Options ---> [*] Driver Core verbose debug messages General setup ---> [*] Configure standard kernel features (for small systems) ---> [*] Load all symbols for debugging/ksymoops
启用选项例如:
slab layer debugging(slab层调试选项) high-memory debugging(高端内存调试选项) I/O mapping debugging(I/O映射调试选项) spin-lock debugging(自旋锁调试选项) stack-overflow checking(栈溢出检查选项) sleep-inside-spinlock checking(自旋锁内睡眠选项)
2 调试原子操作
从内核2.5开发,为了检查各类由原子操作引发的问题,内核提供了极佳的工具。
内核提供了一个原子操作计数器,它可以配置成,一旦在原子操作过程中,进城进入睡眠或者做了一些可能引起睡眠的操作,就打印警告信息并提供追踪线索。
所以,包括在使用锁的时候调用schedule(),正使用锁的时候以阻塞方式请求分配内存等,各种潜在的bug都能够被探测到。
下面这些选项可以最大限度地利用该特性:
CONFIG_PREEMPT = y CONFIG_DEBUG_KERNEL = y CONFIG_KLLSYMS = y CONFIG_SPINLOCK_SLEEP = y
四 引发bug并打印信息
1 BUG()和BUG_ON()
一些内核调用可以用来方便标记bug,提供断言并输出信息。最常用的两个是BUG()和BUG_ON()。
定义在<include/asm-generic>中:
#ifndef HAVE_ARCH_BUG #define BUG() do { printk("BUG: failure at %s:%d/%s()! ", __FILE__, __LINE__, __FUNCTION__); panic("BUG!"); /* 引发更严重的错误,不但打印错误消息,而且整个系统业会挂起 */ } while (0) #endif #ifndef HAVE_ARCH_BUG_ON #define BUG_ON(condition) do { if (unlikely(condition)) BUG(); } while(0) #endif
当调用这两个宏的时候,它们会引发OOPS,导致栈的回溯和错误消息的打印。
※ 可以把这两个调用当作断言使用,如:BUG_ON(bad_thing);
2 dump_stack()
有些时候,只需要在终端上打印一下栈的回溯信息来帮助你调试。这时可以使用dump_stack()。这个函数只在终端上打印寄存器上下文和函数的跟踪线索。
if (!debug_check) { printk(KERN_DEBUG “provide some information…/n”); dump_stack(); }
3 LOG等级
printk和printf一个主要的区别就是前者可以指定一个LOG等级。内核根据这个等级来判断是否在终端上打印消息。内核把比指定等级高的所有消息显示在终端。
可以使用下面的方式指定一个LOG级别:
printk(KERN_CRIT “Hello, world!\n”);
注意,第一个参数并不一个真正的参数,因为其中没有用于分隔级别(KERN_CRIT)和格式字符的逗号(,)。KERN_CRIT本身只是一个普通的字符串(事实上,它表示的是字符串 "<2>";表 1 列出了完整的日志级别清单)。作为预处理程序的一部分,C 会自动地使用一个名为 字符串串联 的功能将这两个字符串组合在一起。组合的结果是将日志级别和用户指定的格式字符串包含在一个字符串中。
内核使用这个指定LOG级别与当前终端LOG等级console_loglevel来决定是不是向终端打印。
下面是可使用的LOG等级:
#define KERN_EMERG "<0>" /* system is unusable */#define KERN_ALERT "<1>" /* action must be taken immediately */ #define KERN_CRIT "<2>" /* critical conditions */#define KERN_ERR "<3>" /* error conditions */#define KERN_WARNING "<4>" /* warning conditions */#define KERN_NOTICE "<5>" /* normal but significant condition */#define KERN_INFO "<6>" /* informational */#define KERN_DEBUG "<7>" /* debug-level messages */#define KERN_DEFAULT "<d>" /* Use the default kernel loglevel */
注意,如果调用者未将日志级别提供给 printk,那么系统就会使用默认值 KERN_WARNING "<4>"(表示只有KERN_WARNING 级别以上的日志消息会被记录)。由于默认值存在变化,所以在使用时最好指定LOG级别。有LOG级别的一个好处就是我们可以选择性的输出LOG。比如平时我们只需要打印KERN_WARNING级别以上的关键性LOG,但是调试的时候,我们可以选择打印KERN_DEBUG等以上的详细LOG。而这些都不需要我们修改代码,只需要通过命令修改默认日志输出级别:
mtj@ubuntu :~$ cat /proc/sys/kernel/printk4 4 1 7mtj@ubuntu :~$ cat /proc/sys/kernel/printk_delay0mtj@ubuntu :~$ cat /proc/sys/kernel/printk_ratelimit5mtj@ubuntu :~$ cat /proc/sys/kernel/printk_ratelimit_burst10
第一项定义了 printk API 当前使用的日志级别。这些日志级别表示了控制台的日志级别、默认消息日志级别、最小控制台日志级别和默认控制台日志级别。printk_delay 值表示的是 printk 消息之间的延迟毫秒数(用于提高某些场景的可读性)。注意,这里它的值为 0,而它是不可以通过 /proc 设置的。printk_ratelimit 定义了消息之间允许的最小时间间隔(当前定义为每 5 秒内的某个内核消息数)。消息数量是由 printk_ratelimit_burst 定义的(当前定义为 10)。如果您拥有一个非正式内核而又使用有带宽限制的控制台设备(如通过串口), 那么这非常有用。注意,在内核中,速度限制是由调用者控制的,而不是在printk 中实现的。如果一个 printk 用户要求进行速度限制,那么该用户就需要调用printk_ratelimit 函数。4 记录缓冲区
内核消息都被保存在一个LOG_BUF_LEN大小的环形队列中。
关于LOG_BUF_LEN定义:
#define __LOG_BUF_LEN (1 << CONFIG_LOG_BUF_SHIFT)
※ 变量CONFIG_LOG_BUF_SHIFT在内核编译时由配置文件定义,对于i386平台,其值定义如下(在linux26/arch/i386/defconfig中): CONFIG_LOG_BUF_SHIFT=18
记录缓冲区操作:
① 消息被读出到用户空间时,此消息就会从环形队列中删除。
② 当消息缓冲区满时,如果再有printk()调用时,新消息将覆盖队列中的老消息。
③ 在读写环形队列时,同步问题很容易得到解决。
※ 这个纪录缓冲区之所以称为环形,是因为它的读写都是按照环形队列的方式进行操作的。
本文来自:https://my.oschina.net/fgq611/blog/113249
http://blog.csdn.net/zxygww/article/details/49782181
http://blog.csdn.net/dumgeewang/article/details/7383460
- 内核调试的一些配置
- 关于内核调试的一些方法
- 关于内核调试的一些方法
- Linux内核关于多核的一些配置
- 内核调试配置选项
- VS2013的一些配置、调试、使用
- linux内核编译,启动,调试及背后的一些事情
- WinDBG+VMware调试内核 【虚拟机坏境下内核调试的安装和配置】
- VMware + WinDbg 配置内核调试
- 应用调试之配置内核输出应用程序的段错误信息
- 应用调试之配置内核输出应用程序的段错误信息
- 内核调试的问题
- Linux 的内核调试
- 内核的调试方法
- cocos creator配置原生平台调试遇到的一些问题
- Windows内核开发调试环境配置详解
- systemtap安装&内核调试环境配置
- virtualbox网络配置和调试linux内核
- Linux 中直接 I/O 机制的介绍
- printf函数缓冲区问题
- springMVC拦截器
- 视频标准研发是怎样进行的?
- 135. Candy
- 内核调试的一些配置
- mugen格斗游戏新手入门--不知火舞简易大招及ai制作
- Linux 下命令行连接Wifi方法
- maven的概念之核心概念(第二章)
- android6.0SDK 删除HttpClient的相关类的解决方法
- 把握美国留学申请时间每一个节点 提前准备语言考试(雅思)
- 过来人的经验和感悟
- 多文件工程的编译-Makefile的简便写法
- PE用法