Linux内核调试--打印调试信息的一种方法
Linux内核调试--打印调试信息的一种方法
Linux内核调试--打印调试信息的一种方法
在console_init()之前是不能通过printk来打印信息的,如何定位问题?
最先运行的是head.S文件中的一段汇编程序,在这里只能使用汇编语言写死循环语句了,如果cpu停住了,说明运行到这里了,如果没有停住就
会重启。那有没有这种情况,cpu没有停住,而是死了或者说不动了?不会,cpu一定是在一直运行着代码,不然就会重启了。
例如:
1: li t0, 0
li t1, 1
bne t0, t1, b1
接下来运行的就是C语言程序了,可以使用for(;;)加入死循环,看cpu是否会停住,在console_init()之后就可以使用printk()输出信息了。
其实在console_init()之前也是可以通过串口输出信息的,串口的输出实际上就是往串口寄存器写字符,再由串口输出。linux启动前,
bootloader肯定已经将串口配置好了,我们做的只是去写那个字符就可以了。
串口的输出大同小异,一般有两个寄存器,一个是data,一个是status。data是来收发字符的寄存器,status是反应收发状态的寄存器,两者
配合使用就能够从串口打印出信息,而不用调用printk()这么高级的函数。
从实际的例子出发,这里有data寄存器,地址为0xfffe0114,status寄存器,地址为0xfffe0110,其0x20位表示是否发送完成。所以在
console_init()之前的c语言函数中我们可以添加如下代码打印'#'。
*(volatile unsigned int *)(0xfffe0114) = '#';
while (!(*(volatile unsigned int *)(0xfffe0110) & 0x20));
这里同样也支持'\n', '\r'等换行退格的输出形式。
如何找到data和status寄存器的地址,还有至于status寄存器的哪一位表示发送完成,这些都可以通过看手册得到。
如果没有手册,也有办法,请按照如下轨迹去找:
/init/main.c -> start_kernel() -> console_init() -> xxxx_console_init() -> register_console()看参数的.write成
员函数,找到字符发送的地方就可以找到了。如果是2.6内核,请查找console_initcall,同样找到 xxxx_console_init() 后面就一样了。
当然,在最开始的汇编代码中也可以这样做,可以自己研究一下,应该不难。
Linuxidc免责声明:本文仅代表作者个人观点,与帮客之家(Linuxidc)无关。其原创性以及文中陈述文字和内容未经本站证实,对本文以及其中全部或者部分内容、文字的真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
评论暂时关闭