学习和研究中前行,并在分享中提升自己

欢迎订阅阿里内推邮件



linux下借助dynamic debug 动态打开debug日志

阅读次数: 230| 时间:2018年4月22日 21:37 | 标签:linux

linux下借助dynamic debug 动态打开debug日志

前言

内核开发的时候我们都会在异常路径上加一些日志来确保当异常发生时能很快的定位。今天,主要给大家介绍通过内核dynamic debug的功能来动态开起和关闭debug日志的打印。

enable 这个feature需要的设置

1.内核CONFIG_DYNAMIC_DEBUG编译项要设置为y 2.需要mount debugfs

mount -t debugfs none /sys/kernel/debug/

3.相关调用接口:pr_debug()/dev_debug()

使用案例

  • 为了验证相关的功能,我们通过一个具体的例子来进行测试。首先,我们写一个简单的模块,具体代码如下:
#include <linux/delay.h> /* usleep_range */                                                                                                                                                                 
#include <linux/kernel.h>                                                       
#include <linux/kthread.h>                                                      
#include <linux/module.h>                                                       

static struct task_struct *kthread1, *kthread2;                                 

static int work_func1(void *data)                                               
{                                                                               
    int i = 0;                                                                  
    while (!kthread_should_stop()) {                                            
        pr_debug("1 %d\n", i);                                                  
        usleep_range(1000000, 1000001);                                         
        i++;                                                                    
        if (i == 10)                                                            
            i = 0;                                                              
    }                                                                           
    return 0;                                                                   
}                                                                               

static int work_func2(void *data)                                               
{                                                                               
    int i = 0;                                                                  
    while (!kthread_should_stop()) {                                            
        pr_debug("2 %d\n", i);                                                  
        usleep_range(1000000, 1000001);                                         
        i++;                                                                    
        if (i == 10)                                                            
            i = 0;                                                              
    }                                                                           
    return 0;                                                                   
}                                                                               

static int myinit(void)                                                            
{                                                                                  
    kthread1 = kthread_create(work_func1, NULL, "mykthread1");                     
    kthread2 = kthread_create(work_func2, NULL, "mykthread2");                     
    wake_up_process(kthread1);                                                     
    wake_up_process(kthread2);                                                     
    return 0;                                                                      
}                                                                                  

static void myexit(void)                                                           
{                                                                                  
    kthread_stop(kthread1);                                                        
    kthread_stop(kthread2);                                                        
}                                                                                  

module_init(myinit)           
  • 支持以module粒度的debug日志的办输出

先编译出一下上面的模块,然后什么正常加载,查看一下dmesg的输出。发现没有任何输出,为了验证该feature,我们做如下操作:

echo 'module kthread_module  +p' > /sys/kernel/debug/dynamic_debug/control

然后,看一下dmesg输出

[root@debug010000002015 ~]# dmesg 
[22142895.065257] 2 3
[22142895.093093] 1 3
[22142896.065287] 2 4
[22142896.093116] 1 4
[22142897.065311] 2 5
[22142897.093138] 1 5
[22142898.065341] 2 6
[22142898.093161] 1 6
[22142899.065371] 2 7
[22142899.093182] 1 7
[22142900.065405] 2 8

然后,我们通过以下命令把debug关闭

echo 'module kthread_module  -p' > /sys/kernel/debug/dynamic_debug/control

注意,开起和关闭的命令唯一区别就是一个是‘+’号,一个是'-'号。再看一下dmesg输出,发现已经没有最新的输出。

  • 支持文件中行粒度的日志输出

有时候,我们只希望输出某个特定行的日志,这时候我们就可以这样设置。以本文中的模块为例

echo "file kthread_module.c line 12 +p" > /sys/kernel/debug/dynamic_debug/control

我们只输出work1的日志,结果如下

[root@debug010000002015 ~]# dmesg 
[22143373.115233] 1 1
[22143374.115261] 1 2
[22143375.115287] 1 3
[22143376.115315] 1 4

可以看到,与上面的区别是,它只输出了work1函数的日志。当然,关闭的话也是一样,只需将'+p'修改为'-p'。

  • 支持函数粒度的日志设置

有些场景,可能我们指定函数要比行数要更好一些。那么以本文中的模块为例子,如果我们只想打开work2函数中的日志输出的话,我们就可以这样设置

echo "func work_func2 +p" > /sys/kernel/debug/dynamic_debug/control 

通过demsg查看日志如下:

22143598.118789] 2 6
[22143599.118811] 2 7
[22143600.118834] 2 8
[22143601.118863] 2 9
[22143602.118886] 2 0
[22143603.118910] 2 1
[22143604.118933] 2 2
[22143605.118955] 2 3
[22143606.118980] 2 4
[22143607.119002] 2 5
[22143608.119025] 2 6
[22143609.119049] 2 7

OK,可以看到work2的日志已经输出了。