用printk来调试驱动程序
先引进错误(不用虚拟地址,直接用物理地址)
编译驱动程序和测试程序并拷贝到网络文件系统里面去
装载驱动程序,运行测试程序
无法卸载驱动,因为程序崩溃,一直占用驱动,智能通过reboot重启
重启后安装驱动看打印
运行测试程序,打印出了26行,就知道是在后面的行死了
原因是访问了非法地址
查看gpfcon
应用程序调用open函数进而调用内核的open函数,进行打印调试(可以折半加打印,不用每行都加)
方法一:
我们可以再内核中使用如下打印语句:
#define DEG_PRINTK printk
//#define DEG_PRINTK(x...) //不想用时定义为空的宏
DEG_PRINTK("%s %s %d\n",_FILE_,_FUNCTION_,_LINE_);
这行打印语句的意思就是讲本行代码所在的文件的名(包括路径)、所在的函数、所在的行打印出来!
当我们需要调试的时候,就使用#define DEG_PRINTK printk这个宏,当不需要调试的时候,就使用#define DEG_PRINTK(x...)这个宏。其中#define DEG_PRINTK(x...)里面的"..."的意思是DEG_PRINTK的参数是可变的!,
当代码比较少的时候,我们可以在每一行都加上这个打印语句,这样很容易就会发现错误的位置!
当代码比较多的时候,我们可以采用对半查找的方法!先在代码中间加上打印语句!然后判断出错位置在打印语句之前还是之后,如果出现在之前,就在之前的代码代码里面再次采用对半查找!
方法二:(系统运行中修改打印级别,从而减少或不打印内核信息,节省时间)
打印级别
printk加上打印级别
如果消息的打印级别msg_log_level(KERN_DEBUG)小于console_loglevel就打印,调整console_loglevel,要打印debug信息,需要把console_loglevel设置为8,因为msg_log_level(KERN_DEBUG)为7
loglevel
当uboot传入的参数有loglevel这个前缀时,后面带的字符串是str会作为参数调用函数loglevel把字符串转化成1个整数赋给值console_loglevel,console_loglevel在里面用到。把console_loglevel这个值改为0 就能把所有打印信息去掉。但可以用dmesg命令打印内核信息
重启后所有的打印信息都没有了
设置成debug级别,console_loglevel为10
会打印所有信息
方法三:,
上面我们说到过,要打印的信息会存放在log_buf中,通过文件/proc/kmsg可以来访问这个buf,然后将信息打印出来。由此我们就想了,我们是否可以构造这样一个mylog_buf,里面存放我们所需要的打印信息,通过一个/proc/kmsg文件可以访问该buf,然后打印出来?答案是肯定的!下面我们就一步步来完成!