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

本文涉及的产品
日志服务 SLS,月写入数据量 50GB 1个月
简介: 内核笔记](四)——内核常见调试手段(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日志并进行多维度分析。
相关文章
|
6月前
|
程序员 编译器 C语言
内核中的打印
内核中的打印
87 0
|
Linux 项目管理
Linux内核基础篇——动态输出调试
Linux内核基础篇——动态输出调试
|
SoC C语言
内核笔记](五)——devmem读写寄存器调试
内核笔记](五)——devmem读写寄存器调试
1441 0
|
Windows
【Windows 逆向】使用 CE 工具挖掘关键数据内存真实地址 ( 数据查找技巧 | 地址访问调试 | 指令选择技巧 | MOV 汇编指令含义 | 基址值搜索 ) ★
【Windows 逆向】使用 CE 工具挖掘关键数据内存真实地址 ( 数据查找技巧 | 地址访问调试 | 指令选择技巧 | MOV 汇编指令含义 | 基址值搜索 ) ★
651 0
【Windows 逆向】使用 CE 工具挖掘关键数据内存真实地址 ( 数据查找技巧 | 地址访问调试 | 指令选择技巧 | MOV 汇编指令含义 | 基址值搜索 ) ★
|
NoSQL Shell
[PWN][进阶篇]使用GDB附加调试64位程序(下)
[PWN][进阶篇]使用GDB附加调试64位程序
253 0
[PWN][进阶篇]使用GDB附加调试64位程序(下)
|
NoSQL
[PWN][进阶篇]使用GDB附加调试64位程序(上)
[PWN][进阶篇]使用GDB附加调试64位程序
519 0
[PWN][进阶篇]使用GDB附加调试64位程序(上)
|
运维 Linux Shell
|
Linux
Linux下控制(统计)文件的生成的C代码实现
不定时地在Linux机器下的某目录中放入文件,文件内容中包含了用户号码、起止时间等字段,编写一程序来统计目前该目录中所有文件中的记录总条数及所有记录中的最早起始时间和最晚结束时间。
1366 0