一、调试接口 在软件开发中,调试永远占着非常重要的地位。毕竟人脑没法按照CPU的方式工作。 1.合理的控制自己的消息打印 消息打印是最原始的调试方式,也是最有用的调试方式。合理的控制自己的打印信息,绝对能事半功倍。 a) release 版本和debug版本 添加宏开关,控制打印信息是否编译。在 release版本中不包含打印信息 b)通过module_param_named()控制打印等级,从而控制打印是否输出 在/sys/module下面的模块里,给内核中驱动模块留下了这个接口,可以很方便的控制输出等级。 static int msm_pm_debug_mask; module_param_named( debug_mask, msm_pm_debug_mask, int, S_IRUGO | S_IWUSR | S_IWGRP ); #define MSM_PM_DPRINTK(mask, level, message, ...) \ do { \ if ((mask) & msm_pm_debug_mask) \ printk(level message, ## __VA_ARGS__); \ } while (0) 2. 内核模块中的打印信息 内核模块中留有丰富的调试接口。 a) debugfs 在代码中看到了 debugfs_create_dir() debugfs_create_u32() 恭喜你,前人已栽好树,找个地方乘凉去吧。搞清楚目录位置,到处相应的数据,分析去吧。 b)CONFIG_DYNAMIC_PRINTK_DEBUG 这是一个开关,通过这一开关,可以打开内核中的一些打印信息。 请参考 kernel/Documentation/dynamic-debug-howto.txt c) proc 其实/proc下也有很多内核导出的信息。 /proc/meminfo /proc/cpuinfo /proc/cmdline --kernel启动参数 /proc/task/ ---列出了系统当前的进程,以及进程的很多信息。 二、分析工具 1. dump_stack() 很方便的打印出当前函数的调用堆栈的函数。使用非常方便,分析内核里的framework非常方便。 2. 找出image中编译的了那个函数。 经常遇到一个函数在多个文件中都有实现,分析很久才能搞清楚到底是哪一个函数。有了下面这个工具,就可以很轻松的知道是哪一个工具了。 arm-eabi-nm -A -a -l -n vmlinux | grep -v '\( [aNUw] \)\|\(__crc_\)\|\( \$[adt]\)' > System.map 这个工具对HAL层的动态库同样有用 3. 有时候,看到kernel里面上万个文件和各种各样的宏,是不是很有干掉一些的冲动?推荐看看stripcc 4. .config kernel里面的Kconfig也是一绝,我经常搞不清楚到底那么错综复杂的依赖关系。不过还好,.config。 这个文件在输出目录下,是kernel编译时,各种CONFIG的配置结果。 所以,如果不确定编译开关是否打开,检查一下这个文件即可。
|
|