目录
文章目录
1.创建log控制公共头文件
#ifndef __DEBUG_H__
#define __DEBUG_H__
#ifdef DEV_DEBUG
#ifdef __KERNER__
/*kernel*/
#define PDEBUG(fmt, args...) printk(KERN_DEBUG "--yuelei--" fmt, ##args)
#else
/*userspace*/
#define PDEBUG(fmt, args...) fprintf(stderr, fmt, ##args)
#endif
#else
#define PDEBUG(fmt, args...)
#endif
#endif
在makefile中添加编译选项,CFLAGS+=-O -g -DDEV_DEBUG,如果要赋值,可以写为DDEV_DEBUG=1
2.kernel打印输出限制
printk_ratelimit()
其作用是用于限制printk的打印数量,使用方法如下:
if(printk_ratelimit())
printk("********");
该函数的速率由下面两个文件控制:
- **
/proc/sys/kernel/printk_ratelimit:
**限制时间间隔,默认值是5 - **
/proc/sys/kernel/printk_ratelimit_burst:
**时间间隔内的最大打印条数,默认值是10
因此,默认情况下,打印速率为每5s最多10条打印
3.带时间戳的打印
加入以下代码,可以实现打印时间戳
struct timeval time1;
do_gettimeofday(&time1);
printk ("[abelard] use new time sec: %ld, usec: %ld. FUNC=%s,LINE=%d \n", time1.tv_sec,time1.tv_usec,__func__,__LINE__);
4.使能kernel中DEBUG宏的方法
a.在顶层makefile中加入KCFLAGS+=-DDEBUG
该方法将会导致所有模块的DEBUG宏将会enable,会产生大量的调试log
b.在driver目录下的Makefile中加入ccflags-y := -DDEBUG
该方法只打开该Makefile所在目录下模块的debug log,但是不含子目录
c.在driver目录下的Makefile中加入subdir-ccflags-y := -DDEBUG
该方法只打开该Makefile所在目录下模块的所有debug log,包含子目录
5.linux kernel printk
默认打印级别设置
a.直接修改printk.h
中CONSOLE_LOGLEVEL_DEFAULT
的定义
b.通过dts中boot argument
设置loglevel
6.linux中获取device name
利用函数dev_name(const struct device *dev)
获得驱动设备的名字
7.kernel中根据函数指针获得函数名
%p: 打印裸指针(raw pointer)。%p除了可以用来打印指针外还可以打印其它的信息
%pF: 可打印函数指针的函数名和偏移地址
%pf: 只打印函数指针的函数名,不打印偏移地址。
如
printk("%pf %pF\n", ptr, ptr) will print:
module_start module_start+0x0/0x62 [hello]
但是为了支持这个功能你需要开启CONFIG_KALLSYMS
选项
8.利用dump_stack追溯kernel中的函数调用
Example code:
static ssize_t **state_store**(struct kobject *kobj, struct kobj_attribute *attr,const char *buf, size_t n)
{
......
dump_stack();
......
}
Example log:
[ 316.185025] CPU: 0 PID: 5350 Comm: sh Tainted: G W 3.14.55-x86_64-g50cbeeb-dirty #3
[ 316.194613] Hardware name: NA 10-LTDN-1/10-LTDN-1, BIOS 5.04.42.0052-A-Z-008 10/29/2014
[ 316.203606] ffff8800527c0460 ffff880047767e78 ffffffff81bcb16a 0000000000000004
[ 316.211984] ffff880047767e98 ffffffff810d96a2 0000000000000004 ffff8800527c0460
[ 316.220368] ffff880047767ea8 ffffffff8143a7cf ffff880047767eb8 ffffffff8123ab2a
[ 316.228769] Call Trace:
[ 316.231544] [<ffffffff81bcb16a>] dump_stack+0x4e/0x7a
[ 316.237332] [<ffffffff810d96a2>] state_store+0x52/0xc0
[ 316.243204] [<ffffffff8143a7cf>] kobj_attr_store+0xf/0x20
[ 316.249379] [<ffffffff8123ab2a>] sysfs_kf_write+0x3a/0x50
[ 316.255550] [<ffffffff8123e6b2>] kernfs_fop_write+0xd2/0x140
[ 316.262016] [<ffffffff811c1d3a>] vfs_write+0xba/0x1d0
[ 316.267799] [<ffffffff811c2739>] SyS_write+0x49/0xb0
[ 316.273496] [<ffffffff81be2973>] sysenter_dispatch+0x7/0x1f
[ 316.279858] [<ffffffff8144666b>] ? trace_hardirqs_on_thunk+0x3a/0x3c
函数的调用顺序为:… >> kobj_attr_store >> state_store >> dump_stack