嵌入式Linux内核驱动调试方法

学习链接:https://xuesong.blog.csdn.net/article/details/109522945?spm=1001.2014.3001.5502

1. printk

printk简介

内核中的打印函数printk(), 通过 printk 可以打印变量或者寄存器的地址和值,printk函数中可以附加不同的日志级别或消息优先级

搜索函数,搜到以后,看函数原形

printk(打印级别 "内容")

printk(KERN_ERR "Fail%d",a);

printk(KERN_ERR "%s:%s:%d\n",__FILE__,__func__,__LINE__);

驱动在哪一个文件,哪一个函数,哪一行

printk("%s:%s:%d\n",__FILE__,__func__,__LINE__);

查看内核打印级别 vi -t  KERN_ERR

include/linux/printk.h

#define KERN_EMERG  "<0>"   /* system is unusable        */(系统不用)

#define KERN_ALERT  "<1>"   /* action must be taken immediately */(被立即处理)

#define KERN_CRIT   "<2>"   /* critical conditions          */(临界条件,临界资源)

#define KERN_ERR    "<3>"   /* error conditions         */(出错)

#define KERN_WARNING    "<4>"   /* warning conditions           */(警告)

#define KERN_NOTICE "<5>"   /* normal but significant condition */(提示)

#define KERN_INFO   "<6>"   /* informational            */(打印信息时候的级别)

#define KERN_DEBUG  "<7>"   /* debug-level messages         */ (调试级别)

0 ------ 7

最高的  最低的

linux@ubuntu:~$ cat  /proc/sys/kernel/printk  4         4          1          7

 终端的级别     消息的默认级别   终端的最大级别  终端的最小级别

#define console_loglevel (console_printk[0])

#define default_message_loglevel (console_printk[1])

#define minimum_console_loglevel (console_printk[2])                                               

#define default_console_loglevel (console_printk[3])

注意:只有当消息的级别大于终端级别,消息才会被显示

修改系统默认的级别

su root

echo 4 3 1 7 > /proc/sys/kernel/printk

虚拟机的默认情况

板子的默认情况: 

修改开发板对应的打印级别

vi  rootfs/etc/init.d/rcS

echo 4 3 1 7 > /proc/sys/kernel/printk

rootfs/etc/init.d/rcS里面添加上以后再起板子,板子的级别就为如下:

安装驱动和卸载驱动时,消息会打印。

 

 2.dump_stack

dump_stack() ,相信从事 Linux 内核或者驱动相关开发的同行对于此函数肯定不陌生。我们经常会用到此函数来对自己的代码进行 debug,可以快速帮助开发者理清函数调用流程,有些时候,只需要在终端上打印一下栈的回溯信息来帮助调试。 dump_stack() 这个函数只在终端上打印寄存器上下文和函数的跟踪线索。 

  1. if (!debug_check) {

  2. printk(KERN_DEBUG “provide some information…/n”);

  3. dump_stack();

  4. }

printk("%sCPU: %d PID: %d Comm: %.20s %s %s %.*s\n", 
	log_lvl, raw_smp_processor_id(), current->pid, current->comm, 
	print_tainted(), init_utsname()->release,
	(int)strcspn(init_utsname()->version, " "),
	init_utsname()->version); 以及

printk("[<%p>] %pS\n", (void *) ip, (void *) ip);

 3.oops

oops是指Linux内核中的错误报告机制,全称为“Out of memory (OOM) killer Process Stopped(内存不足杀掉进程)”。当内核检测到意外的错误时,它会自动解锁已经持有的互斥锁,并打印一条错误消息,然后导致系统宕机。 使用oops的步骤如下: 1.设置内核参数,使它在oops发生时自动记录到系统日志中。可以通过设置/sys/module/kernel /parameters/panic_on_oops参数来实现,将其设置为1。 2. 当oops发生时,Linux内核会记录错误信息,并将它们写入到系统日志中。可以通过使用dmesg命令来查看最近的错误消息,或者通过查看/var/log/messages文件来查看完整信息。 3. 使用oops解码和分析工具,如crash或者ksymoops来处理错误信息,并诊断和修复问题。 4. 如果需要更详细的信息来了解系统的状态和内核操作,可以使用Kdump来收集内存转储,并进行off-line分析。 总之,oops是一种非常重要的工具,可以帮助开发人员和系统管理员快速诊断和修复故障,提高系统的可靠性和稳定性。

36 ssize_t faulty_read(struct file *filp, char __user *buf,
37                     size_t count, loff_t *pos)
38 {
39         int ret;
40         char stack_buf[4];
41
42         /* Let’s try a buffer overflow  */
43         memset(stack_buf, 0xff, 20);		//出错
44         if (count > 4)
45                 count = 4; /* copy 4 bytes to the user */
46         ret = copy_to_user(buf, stack_buf, count);
47         if (!ret)
48                 return count;
49         return ret;
50 }
/

00000000 <faulty_read>:
   0:   e1a0c00d        mov     ip, sp
   4:   e92dd870        stmdb   sp!, {r4, r5, r6, fp, ip, lr, pc}  
   8:   e24cb004        sub     fp, ip, #4      ; 0×4
   c:   e24dd004        sub     sp, sp, #4      ; 0×4,这里为stack_buf[]在栈上分配1个字的空间,局部变量ret使用寄存器存储,因此就不在栈上分配空间了
  10:   e24b501c        sub     r5, fp, #28     ; 0x1c
  14:   e1a04001        mov     r4, r1
  18:   e1a06002        mov     r6, r2
  1c:   e3a010ff        mov     r1, #255        ; 0xff
  20:   e3a02014        mov     r2, #20 ; 0×14
  24:   e1a00005        mov     r0, r5
  28:   ebfffffe        bl      28 <faulty_read+0×28>  //这里在调用memset

  78:   e89da878        ldmia   sp, {r3, r4, r5, r6, fp, sp, pc}

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值