您的位置:首页 > 其它

dynamic debug log输出机制

2012-06-05 15:17 393 查看
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
必须,在kernel的config文件(kernel/arch/arm/configs/semc_lotus_deconfig)中有CONFIG_DEBUG_FS=y

3. 如果需要使用Dynamic debug机制,需要在kernel的config文件(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_HASH和DEBUG_HASH2的定义在kernel/scripts/makefile.lib中

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

DEBUG_HASH2=$(shell ./scripts/basic/hash r5 $(@D)$(modname)) //利用r5 hash算法,计算modname的DEBUG_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_query和ddebug_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 _ddebug中flag字段,还有根据struct
_ddebug中的primary_hash和secondary_hash,来标志global value dynamic_debug_enabled和dynamic_debug_enabled2
对应的位,会在__dynamic_dbg_enabled@kernel/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_enabled和dynamic_debug_enabled2@kernel/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_dbg的log,
关键是如下判断,@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_HASH和DEBUG_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。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: