好难啊!这些东西完全不知道该那些地方入手,只能硬着头皮吸收一些自己可以看得懂的;
有些看得懂,有些看不懂,都不知道怎么查,总算知道为啥底层工程师这么少了;
可不能放弃,内核打我千百遍,我当内核是我爹,混熟了应该就好了吧!
[0x100]常用内核调试方式
[0x110]内核的DEBUG选项
make menuconfig 或者kernel_root_dir/.config 编译内核时,提供的DEBUG 选项及其作用
实例内核版本:kernel-3.4.39 (高亮为实例不支持)
- CONFIG_DEBUG_KERNEL :默认常用DEBUG方式;
- CONFIG_KALLSYMS :oops 输出打开内核标签符号信息,
- CONFIG_DEBUG_SPINLOCK_ :自旋锁操作错误捕获 [调用休眠\使用为初始化锁\重解锁等];
- CONFIG_DEBUG_DRIVER
- CONFIG_MAGIC_SYSRQ
- CONFIG_DEBUG_PAGEALLOC : 释放时移除所有内存页,会导致系统性能降低,仅测试开启
- CONFIG_IKCONFIG_ : 内核配置信息输出到/PROC 目录,仅测试开启
- CONFIG_PROFILING : 跟踪内核挂起,性能调试,仅测试开启
- CONFIG_INIT_DEBUG :检测__init 执行完成后对初始化内存段的违规访问;
- CONFIG_DEBUG_INFO + CONFIG_FRAME_POINTER : 使用gdb 调试内核的选项;
- CONFIG_DEBUG_SLAB :添加内存界限防护值以检查内存溢出错误;
- CONFIG_DEBUG_STACKOVERFLOW + CONFIG_STACK_USAGE
[0x120]内核打印函数 >>printk
[0x121]默认规则
- 日志级别:printk拥有8种日志级别,定义于<linux/kernel.h>;
- 输出条件:必须以‘ \n’ 字符结尾,否则将输出到是/var/log/messages;
- 缓冲类型: __LOG_BUF_LEN 大小的循环缓冲区 存储于/proc/kmsg;
[0x122]终端打印日志级别配置
- 数值1 :标识优先级高于该等级的日志将被输出到屏幕;
- 数值2 :标识默认printk 输出日志等级;
- 数值3 :最高日志优先级;
- 数值4 :最低日志优先级;
- 参数范围 :1-8 对应 Level [0-7];
- 配置文件:优先级指定通常由==/proc/sys/kernel/printk== 文件指定;
[0x123]输出限制
- 速度限制:/proc/sys/kernel/printk_ratelimit
- 间隔限制:/proc/sys/kernel/printk_ratelimit_burst
- 关联函数:int printk_ratelimit(void)
- 函数作用: 根据 printk_ratelimit 文件中设置的阈值,打印次数低于阈值返回1,超过阈值返回0;
[0x130]DEBUG 开关
[0x131] 编译于代码
#undef PDEBUG /*取消该宏名称的定义,防止重复声明*/
#ifdef device_debug /*开启debug标识*/
#ifdef __kernel__ /*处于内核空间 执行的debug方式 基于printk*/
#define PDEBUG(fmt,args...) printk(KERN_DEBUG "device_name:"fmt,##args)
#else /*处于用户空间 执行的debug方式 基于fprintf*/
#define PDEBUG(fmt,args...) fprintf(stderr,fmt,##args)
#endif
#else /*关闭debug标识,去掉宏定义的内容不与输出到伪终端*/
#define PDEBUG(fmt,args...)
#endif
[0x132] 应用于MAKEFILE
DEBUG := y
ifeq($(DEBUG),y)
DEBFLAGS = -O -g -Ddevice_debug
else
DEBFLAGS = -O2
endif
CFLAGS += $(DEBFLAGS)
[0x200]虚拟文件系统 /PROC
用户空间向内核请求关于内核属性与日常设备需求的数据的只读接口
创建调用:实现proc_read 函数–>创建proc文件入口并关联Proc_read
销毁调用:调用宏 remove_proc_entry(name, parent)
[0x210]原生proc文件操作函数接口
[0x211]创建proc目录文件参数解析
创建内核数据入口:绑定Proc_Read函数后可以获取内核数据;
args 1 :虚拟系统文件名,又称入口名
args 2 :proc文件的保护属性,默认为0
args 3 :指定创建proc文件的根目录,如果base =NULL 则在 proc 根目录创建;L;
return :返回为proc 目录结构指针
#include <linux/proc_fs.h>
/*创建proc 文件入口 需要绑定read函数*/
struct proc_dir_entry *create_proc_entry(const char *name, umode_t mode,struct proc_dir_entry *parent)
{
struct proc_dir_entry *ent;
nlink_t nlink;
if (S_ISDIR(mode)) {
if ((mode & S_IALLUGO)