目录

1 将驱动程序改错

2 调试


1 将驱动程序改错

我们在点灯的函数里面增加一个死循环,

编译完之后,加载,测试,发现系统卡死。

2 调试

我们的系统不管在做什么事情,系统时钟中断是永远都在进行的,

在内核中搜索Timer Tick,

static struct irqaction s3c2410_timer_irq = {.name      = "S3C2410 Timer Tick",.flags        = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,.handler   = s3c2410_timer_interrupt,
};

可以找到这个中断对应的处理函数 。

/** IRQ handler for the timer*/
static irqreturn_t
s3c2410_timer_interrupt(int irq, void *dev_id)
{write_seqlock(&xtime_lock);timer_tick();write_sequnlock(&xtime_lock);return IRQ_HANDLED;
}

我们在里面增加打印,

/** IRQ handler for the timer*/
static irqreturn_t
s3c2410_timer_interrupt(int irq, void *dev_id)
{//如果10秒钟之内都是同一个进程再运行,就打印static pid_t pre_pid;static int cnt = 0;if(pre_pid == current->pid){cnt++;}else{cnt = 0;pre_pid = current->pid;}if(cnt == 10*HZ){cnt = 0;printf("s3c2410_timer_interrupt: pid = %d, task name = %s\n", currrent->pid,current->comm);}write_seqlock(&xtime_lock);timer_tick();write_sequnlock(&xtime_lock);return IRQ_HANDLED;
}

这样我们就可以知道在哪个进程里面导致系统卡死,然后重新编译内核,然后重启系统使用新内核启动,然后加载我们的驱动程序,并测试,系统卡死

从这里可以知道是哪个进程卡死了,但是我们还想知道是卡死在这个进程的哪里,我们知道在执行中断函数之前,有个保存现场的操作,那么我们可以把寄存器的值打印出来,把PC打印出来

当发生中断时,会跳到0xFFFF0018这里,然后去asm_do_IRQ保存现场,

在内核中搜asm_do_IRQ

asmlinkage void asm_do_IRQ(unsigned int irq, struct pt_regs *regs)
{struct pt_regs *old_regs;struct irq_desc *desc = irq_desc + irq;unsigned short pending, other_ints;old_regs = set_irq_regs(regs);/** Some hardware gives randomly wrong interrupts.  Rather* than crashing, do something sensible.*/if (irq >= NR_IRQS)desc = &bad_irq_desc;irq_enter();generic_handle_irq(irq);/* If we're the only interrupt running (ignoring IRQ15 which is forsyscalls), lower our priority to IRQ14 so that softirqs run atthat level.  If there's another, lower-level interrupt, irq_exitwill defer softirqs to that.  */CSYNC();pending = bfin_read_IPEND() & ~0x8000;other_ints = pending & (pending - 1);if (other_ints == 0)lower_to_irq14();irq_exit();set_irq_regs(old_regs);
}

我们的现场就保存在pt_regs里面,

/** This struct defines the way the registers are saved on system* calls.** We don't save all floating point register because the kernel* is compiled to use only a very small subset, so the other are* untouched.** THIS STRUCTURE MUST BE A MULTIPLE 16-BYTE IN SIZE* (because the memory stack pointer MUST ALWAYS be aligned this way)**/
struct pt_regs {/* The following registers are saved by SAVE_MIN: */unsigned long b6;       /* scratch */unsigned long b7;      /* scratch */unsigned long ar_csd;           /* used by cmp8xchg16 (scratch) */unsigned long ar_ssd;           /* reserved for future use (scratch) */unsigned long r8;     /* scratch (return value register 0) */unsigned long r9;        /* scratch (return value register 1) */unsigned long r10;       /* scratch (return value register 2) */unsigned long r11;       /* scratch (return value register 3) */unsigned long cr_ipsr;       /* interrupted task's psr */unsigned long cr_iip;      /* interrupted task's instruction pointer *//** interrupted task's function state; if bit 63 is cleared, it* contains syscall's ar.pfs.pfm:*/unsigned long cr_ifs;unsigned long ar_unat;     /* interrupted task's NaT register (preserved) */unsigned long ar_pfs;     /* prev function state  */unsigned long ar_rsc;     /* RSE configuration *//* The following two are valid only if cr_ipsr.cpl > 0 || ti->flags & _TIF_MCA_INIT */unsigned long ar_rnat;       /* RSE NaT */unsigned long ar_bspstore; /* RSE bspstore */unsigned long pr;     /* 64 predicate registers (1 bit each) */unsigned long b0;      /* return pointer (bp) */unsigned long loadrs;      /* size of dirty partition << 16 */unsigned long r1;      /* the gp pointer */unsigned long r12;      /* interrupted task's memory stack pointer */unsigned long r13;        /* thread pointer */unsigned long ar_fpsr;      /* floating point status (preserved) */unsigned long r15;       /* scratch *//* The remaining registers are NOT saved for system calls.  */unsigned long r14;       /* scratch */unsigned long r2;      /* scratch */unsigned long r3;      /* scratch *//* The following registers are saved by SAVE_REST: */unsigned long r16;        /* scratch */unsigned long r17;     /* scratch */unsigned long r18;     /* scratch */unsigned long r19;     /* scratch */unsigned long r20;     /* scratch */unsigned long r21;     /* scratch */unsigned long r22;     /* scratch */unsigned long r23;     /* scratch */unsigned long r24;     /* scratch */unsigned long r25;     /* scratch */unsigned long r26;     /* scratch */unsigned long r27;     /* scratch */unsigned long r28;     /* scratch */unsigned long r29;     /* scratch */unsigned long r30;     /* scratch */unsigned long r31;     /* scratch */unsigned long ar_ccv;      /* compare/exchange value (scratch) *//** Floating point registers that the kernel considers scratch:*/struct ia64_fpreg f6;        /* scratch */struct ia64_fpreg f7;      /* scratch */struct ia64_fpreg f8;      /* scratch */struct ia64_fpreg f9;      /* scratch */struct ia64_fpreg f10;     /* scratch */struct ia64_fpreg f11;     /* scratch */
};

那么我们可以把想要的寄存器打印出来,

然后重新编译内核,启动,然后ismod加载驱动程序,运行测试程序,

./firstdrvtest on
asm_do_IRQ => s3c2410_timer_interrupt : pid = 752, task name = firstdrvtest
pc = bf000084
asm_do_IRQ => s3c2410_timer_interrupt : pid = 752, task name = firstdrvtest
pc = bf000084   // 对于中断, pc-4才是发生中断瞬间的地址

然后就可以根据PC确定出错位置,先看一下加载的驱动的函数地址范围

cat /proc/kallsyms > kallsyms.txt

然后可以在里面搜索bf000084,搜索不到就搜bf0000,然后可以

那么就是first_drv模块,然后反汇编这个模块,找到84的位置

  3c:    e1a0c00d    mov ip, sp40:   e92dd800    stmdb   sp!, {fp, ip, lr, pc}44:    e24cb004    sub fp, ip, #4  ; 0x448:    e24dd004    sub sp, sp, #4  ; 0x44c:    e3cd3d7f    bic r3, sp, #8128   ; 0x1fc050: e3c3303f    bic r3, r3, #63 ; 0x3f54:   e5933008    ldr r3, [r3, #8]58: e0910002    adds    r0, r1, r25c:   30d00003    sbcccs  r0, r0, r360:   33a03000    movcc   r3, #0  ; 0x064:    e3530000    cmp r3, #0  ; 0x068:    e24b0010    sub r0, fp, #16 ; 0x106c:   1a00001c    bne e4 <init_module+0x5c>70: ebfffffe    bl  70 <first_drv_write+0x34>74: ea00001f    b   f8 <init_module+0x70>78: e3520000    cmp r2, #0  ; 0x07c:    11a01002    movne   r1, r280:   1bfffffe    blne    80 <first_drv_write+0x44>       // 卡死的地方84:  ea00001f    b   108 <init_module+0x80>

虽然出错的位置打印出来PC是84,但是我们之前知道,中断处理完之后返回的位置是PC-4,所以出错的位置在80.

  80:    1bfffffe    blne    80 <first_drv_write+0x44>       // 卡死的地方

这就是那个死循环,永远跳到80.

Linux驱动调试之修改系统时钟中断定位系统僵死问题相关推荐

  1. Linux驱动调试中的Debugfs的使用简介

    Linux驱动调试中的Debugfs的使用简介 (2012-03-31 14:14) 在调试linux驱动的时候,可以用debugfs来调试,debugfs类似字符设备驱动一样,甚至更简单,不需要主设 ...

  2. Linux驱动调试中的Debugfs的使用简介 CONFIG_DEBUG_FS 的功能与配置

    Linux驱动调试中的Debugfs的使用简介 (2012-03-31 14:14) 在调试linux驱动的时候,可以用debugfs来调试,debugfs类似字符设备驱动一样,甚至更简单,不需要主设 ...

  3. linux使用date命令修改系统日期,使用date命令设置CentOS Linux修改系统日期和时间...

    您可以使用date命令来修改CentOS Linux的时间 修改日期: 将时间设置为2014年6月20日的命令如下: #date -s 2014年6月20日 修改时间: 将系统时间设置为14:20:0 ...

  4. linux驱动调试--oops信息

    在移植dm9000 时被一个错误困扰了很久,当时手里只有printk调试手段,觉得自己应该升级下了,先学习了根据oops信息来调试. 先构造一个错误,insmod后抛出如下信息 我们着重看这几句 PC ...

  5. linux驱动调试--段错误之oops信息分析

    原文地址 http://blog.chinaunix.net/xmlrpc.php?r=blog/article&uid=29401328&id=4923447 发生段错误原因就是访问 ...

  6. linux 下Qt 如何修改系统时间

    Qt 提供日期时间的类有 QDate QTime 和QDateTime,这三个类. 一.获取系统时间 可以通过三个静态函数来获取 1.QDate::currentDate() 来获取当前系统的日期 2 ...

  7. Linux驱动段错误,linux驱动调试--段错误之oops信息分析

    下面根据Oops信息来分析一下段错误 first_drv.c 点击(此处)折叠或打开 #include #include #include #include #include #include #in ...

  8. linux驱动调试技巧:灌寄存器---------以mma7660为例

    本文可以使用linux的cat echo命令直接设置mma7660的寄存器的值 部分driver代码如下: static DEVICE_ATTR(mma7660_regs, S_IRUGO | S_I ...

  9. linux驱动调试--段错误之栈信息分析

    转自:http://blog.chinaunix.net/xmlrpc.php?r=blog/article&uid=29401328&id=4923529 接着上一篇来分析一下Oop ...

最新文章

  1. 09CSS元素显示模式
  2. http://wenku.baidu.com/view/26afdb8371fe910ef12df8ccRevit采用DWG和FBX两种格式导入3D max方法的总结...
  3. 可能是GitHub上最好用的文字语法校验工具
  4. 菜鸟自学数据结构系列——(一)如何写出能够在VC下运行的单链表生成程序
  5. 基础知识收藏(ASP.NET的OnClientClick与OnClick事件)-2013.07.10
  6. android 官方教程中文版
  7. 深入互联网广告中的出价模式(上)— 基础出价模式
  8. FastReport使用方法(C/S版)
  9. RIP RETE时间获得PHREAKY
  10. CentOS7升级内核kernel5.0
  11. 2021暨南大学计算机技术上岸经验贴
  12. mini139聊天软件
  13. 实现asp程序调用摄像头并控制摄像头进行拍照
  14. [re入门]音乐文件加密破解
  15. CSDN博客去除上传的图片水印
  16. Kindle 可旋转桌面时钟
  17. file.exists()方法,明明存在,
  18. Android异步加载图像(含线程池,缓存方法)
  19. 摩尔定律,梅特卡夫定律和科斯定律
  20. 长高不仅靠遗传,让孩子再次长高的秘诀都在这

热门文章

  1. 如何让你的阿里博客排在百度的首页
  2. Android各版本市场占有率
  3. 网站关键词优化技术:如何对关键词分类细分处理
  4. vc 坐标系统与影射模式
  5. 关于车路协同的几点质疑与回应——天翼交通总经理王劲答记者问
  6. 2022年1月时事政治行业微信视频号企业认证排行榜:中央电视台运营的3个视频号上榜,央视新闻再度蝉联榜首(附月榜TOP20详单)
  7. 日语计算机专业学生自我介绍,计算机系毕业生的自我介绍
  8. 项目__网页版聊天室
  9. 记者成互联网公司老板,他把猪八戒网做到市值百亿
  10. BGP路由黑洞及解决方案