现在的位置: 首页 > 综合 > 正文

dynamic debug log输出机制

2013年10月06日 ⁄ 综合 ⁄ 共 5077字 ⁄ 字号 评论关闭

dynamic debug log输出机制

0. 注意该机制只对 dev_dbg -> dynamic_dev_dbg
定义的debug log输出加以控制

1. 如何使用:(kernel/Documentation/dynamic-debug-howto.txt

                mkdir /data/debugfs

                mount -t debugfs none /data/debugfs

                echo -n 'file ab8500_fg.c +p' > /data/debugfs/dynamic_debug/control  //增加该文件dynamic debug的输出

                echo -n 'file ab8500_fg.c -p' > /data/debugfs/dynamic_debug/control   //去掉该文件dynamic debug的输出

2. 如果想使用debugfs
必须,在kernelconfig文件(kernel/arch/arm/configs/semc_lotus_deconfig)中有CONFIG_DEBUG_FS=y

3. 如果需要使用Dynamic debug机制,需要在kernelconfig文件(kernel/arch/arm/configs/semc_lotus_deconfig)中有CONFIG_DYNAMIC_DEBUG=y

4. dev_dbg@kernel/include/linux/device.h
->
dynamic_dev_dbg@kernel/include/linux/dynamic_debug.h

                                #define dynamic_dev_dbg(dev, fmt, ...) do {                                                     \

                                static struct _ddebug descriptor                                                                \

                                __used                                                                                                                 \

                               
__attribute__((section("__verbose"), aligned(8))) =                    \

                                { KBUILD_MODNAME, __func__, __FILE__, fmt, DEBUG_HASH,               \

                                                DEBUG_HASH2, __LINE__, _DPRINTK_FLAGS_DEFAULT };           \

                                if (__dynamic_dbg_enabled(descriptor))                                                             \

                                                dev_printk(KERN_DEBUG, dev, fmt, ##__VA_ARGS__);               \

                                } while (0)

                a. define
最终会展开在被调用dev_dbg函数的c文件中,也就是KBUILD_MODNAME, __func__, __FILE__, __LINE__
会有对应的字符串

                b. _DPRINTK_FLAGS_DEFAULT=0;

                c. DEBUG_HASHDEBUG_HASH2的定义在kernel/scripts/makefile.lib

                                DEBUG_HASH=$(shell ./scripts/basic/hash djb2 $(@D)$(modname))   //利用djb2 hash算法,计算modnameDEBUG_HASH
value;

                                DEBUG_HASH2=$(shell ./scripts/basic/hash r5 $(@D)$(modname))         //利用r5 hash算法,计算modnameDEBUG_HASH2
value;

                d. 分析 kernel/scripts/basic/hash.c,会生成out/target/product/lotus/obj/kernel/scripts/basic/hash
shell
可执行文件

                e. 在编译连接完成后,该 descriptor
值会被保存到 data section __verbose

5. dynamic_debug_init@kernel/lib/dynamic_debug.c

                a. dir = debugfs_create_dir("dynamic_debug", NULL);

                b. file = debugfs_create_file("control", 0644, dir, NULL, &ddebug_proc_fops); //debugfs文件系统中创建dynamic_debug/control
文件

                c. 通过__start___verbose__stop___verbose@kernel/include/asm-generic/vmlinux.lds.h中,实际上是获取保存在__verbose区的
struct _ddebug
数据(就是前面编译后添加到data section__verbose

                d. 如果是不同的modname,就添加到ddebug_tables
中,也就是所有dynamic_dev_dbg的模块(modname),文件(__FILE__),(__LINE__),函数(__func__),是否输出的flag,对应的hash
value
都会逐条保存到ddebug_tables

6. 分析 echo -n 'file ab8500_charger.c +p' > /data/debugfs/dynamic_debug/control
的实际操作

                a. 通过system call,debugfs文件系统会调用到ddebug_proc_write,ddebug_parse_queryddebug_parse_flags@kernel/lib/dynamic_debug.c分析传入的参数字符串

                b. 在ddebug_change@kernel/lib/dynamic_debug.c中,会根据modname, __FILE__, __LINE__
__func__
信息在ddebug_tables找到对应的item.

                c. 然后根据输入的是 +p-p ,来标志struct _ddebugflag字段,还有根据struct
_ddebug
中的primary_hashsecondary_hash,来标志global value dynamic_debug_enableddynamic_debug_enabled2
对应的位,会在__dynamic_dbg_enabledkernel/include/linux/dynamic_debug.h用到

7. 分析 #cat /data/debugfs/dynamic_debug/control的实际操作

                a. ddebug_proc_open中有err = seq_open(file, &ddebug_proc_seqops);应用了seq
file
的读写机制

                b. 然后seq_read,利用seq file机制逐个读出和显示ddebug_tables中的内容

8. long long dynamic_debug_enableddynamic_debug_enabled2kernel/lib/dynamic_debugc,用于标志某个mod(可包含一个或多个文件,比如ab8500_fg
mod,
目前只包含ab8500_fg.c file)是否可以输出debug log的模块
最多可以标志64*64=4096
dev_debug/dynamic_dev_dbg.

9. 是否输出dev_log/dynamic_dev_dbglog,
关键是如下判断,@kernel/include/linux/dynamic_debug.h

                                #define __dynamic_dbg_enabled(dd)  ({                  \

                                int __ret = 0;                                                                                                           \

                                if (unlikely((dynamic_debug_enabled & (1LL << DEBUG_HASH)) &&            \

                                                                (dynamic_debug_enabled2 & (1LL << DEBUG_HASH2))))   \

                                                                                if (unlikely(dd.flags))                                           \

                                                                                                __ret = 1;                                                 \

                                __ret; })

                a.
dynamic_debug_enabled
dynamic_debug_enabled2就是前面分析的是否输出该modname的两个long long的组合标志位

                b. DEBUG_HASHDEBUG_HASH2
如前面所解释

           c. dd.flag
默认为_DPRINTK_FLAGS_DEFAULT,但通过debugfs文件系统,最终操作ddebug_proc_write函数,会设置为_DPRINTK_FLAGS_PRIN_DPRINTK_FLAGS_DEFAULT

10. debugfs 文件系统中的内容保存在那?????内存中,类似proc

11. 小结:如果你需要用到dynamic debug info,
你需要在你的 .c
文件中查看是否用到了dev_log
输出log

抱歉!评论已关闭.