• 38.Linux驱动调试-根据系统时钟定位出错位置


    当内核或驱动出现僵死bug,导致系统无法正常运行,怎么找到是哪个函数的位置导致的?

    答,通过内核的系统时钟,因为它是由定时器中断产生的,每隔一定时间便会触发一次,所以当CPU一直在某个进程中时,我们便在中断函数中打印该进程的信息

     


    1.先来回忆下

    在之前的第5章内核中断运行过程:http://www.cnblogs.com/lifexy/p/7506504.html分析过,当内核中断产生时,会做以下几步:

    • 1)pc-4(计算返回地址值),然后将各个寄存器值存到sp栈里
    • 2)获取中断号,获取sp地址,然后调用asm_do_IRQ()

    1.1其中asm_do_IRQ函数原型如下所示:

    asmlinkage void __exception asm_do_IRQ(unsigned int irq, struct pt_regs *regs);  
                             //irq:中断号        *regs:发生中断前的各个寄存器基地址(=sp基地址)

    1.2其中pt_regs结构体成员如下图所示,用来保存各个寄存器内容的数组:

     

    2.所以本节目的,修改asm_do_IRQ()函数,添加如下内容:

    • 1)判断irq若等于系统时钟的irq,然后cnt++
    • 2)若在10s后,获取的进程没有改变,便打印:进程名字、PID、(regs-> ARM_pc)-4

    (PS: 为什么要打印PC-4?    因为此时的PC是返回地址,而PC-4才是CPU运行的地址)

     

    3.首先来找到系统时钟的中断号irq

    输入#cat /proc/interrupt,如下图所示:

     

    其中中断号来自 linux-2.6.22.6includeasm-armarch-s3c2410Irqs.h

    S3C2410 Timer Tick,就是我们的系统时钟计数值,在内核中就是jiffies这个全局变量,每隔一段时间+1。

    所以S3C2410 Timer Tick的中断号为30

     

    4.接下来便来修改asm_do_IRQ()函数

    在asm_do_IRQ()中,添加以下带红色的字

    asmlinkage void __exception asm_do_IRQ(unsigned int irq, struct pt_regs *regs)

    {

             struct pt_regs *old_regs = set_irq_regs(regs);

             struct irq_desc *desc = irq_desc + irq;  

       #ifdef 1

        static pid_t pre_pid;                    //进程号  

        static int cnt=0;                          //计数值

        if(irq==30)          //判断irq中断号,是否等于系统时钟

        {  

            if(pre_pid==current->pid)

            {   

                cnt++;

            }

            else

            {

                cnt=0;   

                pre_pid=current->pid;

            }

            if(cnt==10*HZ)   //超时10s

            {

            cnt=0;

            printk("s3c2410_timer_interrupt : pid = %d, task_name = %s ",current->pid,current->comm);

            printk("pc = %08x ",regs->ARM_pc);

            }

    }     

    #endif

             ... ...

    }

    1)其中current是一个宏,为task_struct结构体,表示当前运行的进程信息,该宏通过get_current()来获取进程信息,位于includeasm-armcurrent.h

    current->pid:当前进程的PID号

    current->com:表示当前进程的name

    2) HZ也是一个宏,代表每S的频率,比如每隔10ms加1,那么HZ就等于100

    5.测试运行

    接下来,我们便安装一个带有while(1)死循环的驱动,然后通过测试程序,内核便会一直在while(1)死循环,进入僵死状态。

    由于修改了asm_do_IRQ()函数后,所以会打印下图信息:

     

    5.1 然后便可以通过pc值=bf0000C,就能查找在哪个函数出错

    (参考:http://www.cnblogs.com/lifexy/p/8006748.html)

  • 相关阅读:
    Java Web 项目学习(二) 发送邮件
    Java Web 项目学习(一) 项目调试与版本控制
    org.mybatis.spring.MyBatisSystemException: nested exception is org.apache.ibatis.executor.ExecutorException: A query was run and no Result Maps were found for the Mapped Statement
    拓扑排序
    Java中的<< 和 >> 和 >>>
    Java Web 项目学习(一) Spring MVC 入门
    Java Web 项目学习(一) Spring 入门
    oracleDBA-D1
    Linux运维(3年以内)
    数据库DBA(3年以内需求)
  • 原文地址:https://www.cnblogs.com/lifexy/p/8024415.html
Copyright © 2020-2023  润新知