内核笔记](四)——内核常见调试手段(printf、dump_stack、devmem)

简介: 内核笔记](四)——内核常见调试手段(printf、dump_stack、devmem)

一、内核调试——printk


0a2653c851af460fa595bd959398a8f1.png

printk在内核源码中用来记录日志信息的函数,只能在内核源码范围内使用。用法和printf非常相似

printk函数主要做两件事情:第一件就是将信息记录到log中,而第二件事就是调用控制台驱动来将信息输出。


1.日志级别


printk相比printf来说还多了个:日志级别的设置,用来控制printk打印的这条信息是否在终端上显示的,当日志级别的数值小于控制台级别时,printk要打印的信息才会在控制台打印出来,否则不会显示在控制台!


在我们内核中一共有8种级别,他们分别为


#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   */


2.控制台等级


#define MINIMUM_CONSOLE_LOGLEVEL  1   /*可以使用的最小日志级别*/
#define DEFAULT_CONSOLE_LOGLEVEL  7 /*比KERN_DEBUG 更重要的消息都被打印*/
#define DEFAULT_MESSAGE_LOGLEVEL 4 /* KERN_WARNING */
int console_printk[4] = {
DEFAULT_CONSOLE_LOGLEVEL,/*控制台日志级别,优先级高于该值的消息将在控制台显示*/
/*默认消息日志级别,printk没定义优先级时,打印这个优先级以上的消息*/
DEFAULT_MESSAGE_LOGLEVEL,
/*最小控制台日志级别,控制台日志级别可被设置的最小值(最高优先级)*/
MINIMUM_CONSOLE_LOGLEVEL,
DEFAULT_CONSOLE_LOGLEVEL,/* 默认的控制台日志级别*/
};


二、动态打印


在系统运行时候,动态打印可以由系统维护者动态打开内核子系统的打印,可以有选择性地打开某些模块的打印,而printk是 全局的,只能设置打印等级。要使用动态打印,必须在内核配置时打开CONFIG_ DYNAMIC_ _DEBUG宏。 .


0a2653c851af460fa595bd959398a8f1.png

p:打开动态打印语句。.

f:打印函数名

l:打印行号

m:打印模块名字

t:打印线程ID


2.1 dynamic动态打印转为printk正常打印.


0eacb84100b54626af849e6b562bf92a.png


三、dump_stack


对于大型驱动,想要知道某个回调函数由谁调用,非常困难。到底有没有办法知道呢?回答是肯定的,通过内核提供的接口dump_stack()可以满足要求。其实能够想到使用dump_stack()来跟踪,是根据当内核发生panic时候,也会主动调用该接口,所以我们可以在调试过程中主动调用该接口来进行测试。


0a2653c851af460fa595bd959398a8f1.png


四、devmem


在Linux开发中着实用到的调试工具并不是很多。devmem的方式是提供给驱动开发人员,在应用层能够侦测内存地址中的数据变化,以此来检测驱动中对内存或者相关配置的正确性验证。是应用程序通过mmap函数实现对/dev/mem驱动中mmap方法的使用,映射了设备的内存到用户空间,实现对这些物理地址的读写操作。

memdev:直接读写内存。


使用方法

devmem的使用方式:

语法: devmem ADDRESS [WIDTH [VALUE]]

ADDRESS :要直接读写的地址

WIDTH :指定读写资料的位数(8/16/32…

VALUE :要写入的资料


读32位: devmem 0x98000000

读16位: devmem 0x98000000 16

读8位: devmem 0x98000000 8


写32位: devmem 0x98000000 32 0x12345678

写16位: devmem 0x98000000 16 0x1234

写8位: devmem 0x98000000 8 0x12


相关实践学习
日志服务之使用Nginx模式采集日志
本文介绍如何通过日志服务控制台创建Nginx模式的Logtail配置快速采集Nginx日志并进行多维度分析。
相关文章
|
3月前
|
程序员 编译器 C语言
内核中的打印
内核中的打印
47 0
|
7月前
|
Linux 项目管理
Linux内核基础篇——动态输出调试
Linux内核基础篇——动态输出调试
|
SoC C语言
内核笔记](五)——devmem读写寄存器调试
内核笔记](五)——devmem读写寄存器调试
1055 0
|
Windows
【Windows 逆向】使用 CE 工具挖掘关键数据内存真实地址 ( 数据查找技巧 | 地址访问调试 | 指令选择技巧 | MOV 汇编指令含义 | 基址值搜索 ) ★
【Windows 逆向】使用 CE 工具挖掘关键数据内存真实地址 ( 数据查找技巧 | 地址访问调试 | 指令选择技巧 | MOV 汇编指令含义 | 基址值搜索 ) ★
526 0
【Windows 逆向】使用 CE 工具挖掘关键数据内存真实地址 ( 数据查找技巧 | 地址访问调试 | 指令选择技巧 | MOV 汇编指令含义 | 基址值搜索 ) ★
|
NoSQL Shell
[PWN][进阶篇]使用GDB附加调试64位程序(下)
[PWN][进阶篇]使用GDB附加调试64位程序
220 0
[PWN][进阶篇]使用GDB附加调试64位程序(下)
|
NoSQL
[PWN][进阶篇]使用GDB附加调试64位程序(上)
[PWN][进阶篇]使用GDB附加调试64位程序
435 0
[PWN][进阶篇]使用GDB附加调试64位程序(上)