歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Linux綜合 >> Linux內核

Linux內核線程死鎖或死循環之後如何讓系統宕機重啟

在開發內核模塊或驅動時,如果處理失誤,導致內核線程中出現死鎖或者死循環,你會發現,除了重啟之外,你沒有任何可以做的。這時你的輸入不起任何作用,終端(不是指遠程的ssh工具)只會在那重復的輸出類似“BUG: soft lockup - CPU#0 stuck for 67s! [fclustertool:2043]”,更無奈的是你重啟之後導致系統掛起的堆棧信息也看不到,你所能做的就是一遍遍的加調試信息,一遍遍的重啟機器(這是我的經歷,現在想想很傻)。

這種情況你肯定不是第一個遇到的,所以內核肯定會提供處理這種情況的一些機制。但是如何來找到這些機制在哪個地方,或者說根據什麼信息去google呢?最有用的就是這句話“BUG: soft lockup - CPU#0 stuck for 67s! [fclustertool:2043]”,因為這句話提供你的信息量很大。首先,這條信息可以輸出,說明即使發生死鎖或者死循環,還是有代碼可以執行。第二,可以通過這個日志信息,找到對應的處理函數,這個函數所在的模塊就是用來處理CPU被過度使用時用到的。所以通過這個事情,可以看到內核打印出的只言片語都有可能成為你解決問題的關鍵,一定要從重視這些信息,從中找出有用的東西。

我經常看的內核版本是官方的2.6.32內核,這個版本中我找到的函數是softlockup_tick(),這個函數在時鐘中斷的處理函數run_local_timers()中調用。這個函數會首先檢查watchdog線程是否被掛起,如果不是watchdog線程,會檢查當前占有CPU的線程占有的時間是否超過系統配置的阈值,即softlockup_thresh。如果當前占有CPU的時間過長,則會在系統日志中輸出我們上面看到的那條日志。接下來才是最關鍵的,就是輸出模塊信息、寄存器信息和堆棧信息,檢查softlockup_panic的值是否為1。如果softlockup_panic為1,則調用panic()讓內核掛起,輸出OOPS信息。代碼如下所示:

/*
* This callback runs from the timer interrupt, and checks
* whether the watchdog thread has hung or not:
*/
void softlockup_tick(void)
{
    int this_cpu = smp_processor_id();
    unsigned long touch_timestamp = per_cpu(touch_timestamp, this_cpu);
    unsigned long print_timestamp;
    struct pt_regs *regs = get_irq_regs();
    unsigned long now;
    ......

    /* Warn about unreasonable delays: */
    if (now <= (touch_timestamp + softlockup_thresh))
        return;

    per_cpu(print_timestamp, this_cpu) = touch_timestamp;
    spin_lock(&print_lock);
    printk(KERN_ERR "BUG: soft lockup - CPU#%d stuck for %lus! [%s:%d]\n",
            this_cpu, now - touch_timestamp,
            current->comm, task_pid_nr(current));
    print_modules();
    print_irqtrace_events(current);
    if (regs)
        show_regs(regs);
    else
        dump_stack();
    spin_unlock(&print_lock);


    if (softlockup_panic)
        panic("softlockup: hung tasks");
}

Copyright © Linux教程網 All Rights Reserved