當內核或驅動出現僵死bug,導致系統無法正常運行,怎麼找到是哪個函數的位置導致的? 答,通過內核的系統時鐘,因為它是由定時器中斷產生的,每隔一定時間便會觸發一次,所以當CPU一直在某個進程中時,我們便在中斷函數中列印該進程的信息 1.先來回憶下 在之前的第5章內核中斷運行過程:http://www. ...
當內核或驅動出現僵死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.6\include\asm-arm\arch-s3c2410\Irqs.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\n",current->pid,current->comm);
printk("pc = %08x\n",regs->ARM_pc);
}
}
#endif
... ...
}
1)其中current是一個巨集,為task_struct結構體,表示當前運行的進程信息,該巨集通過get_current()來獲取進程信息,位於include\asm-arm\current.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)