我之前已經寫了lockup問題的檢測原理,本來就來嘗試梳理一下soft lockup問題觸發場景和解決方法。
首先需要明確一點soft lockup是一類問題,引起它的原因也是各有不同,本文只是嘗試做一些梳理,把一些具有共通性的特點的問題做一些總結,可能存在有不全面的地方。
第一種場景:spinlock死鎖場景
對於這種場景,其實很好理解,當a-b/b-a死鎖發生的時候,兩個程序分別去獲取對方持有的鎖,那麼又都是spinlock,我們知道spinlock是會關閉搶占的,並且是忙等待鎖,最終會造成執行cpu上的watchdog執行緒無法被排程執行。這是比較好理解的乙個場景。
針對這個場景如何識別呢,我們從核心crash的堆疊中是可以看得一二的,肯定會有一些程序的堆疊是處於獲取鎖的過程中的,可以在呼叫棧中看到spin_lock相關的一些函式呼叫。那麼針對這一種場景,我們可以利用crash去查詢到spinlock結構體,並定位持有該鎖的程序,如果兩個程序互相持有對方要獲取的鎖,那麼基本確認是這種死鎖型別了。
第二種場景:核心繁忙
所謂的核心繁忙,也就是說核心長時間的在處理事務,而watchdog得不到執行,那麼假如我在自己的核心模組中寫了乙個死迴圈,那麼是不是一定會觸發soft lockup呢?其實不然,死迴圈執行並不一定會導致soft lockup,那是因為程序的執行是受到核心排程器管理的,並不是你寫個死迴圈,它就會一直占用cpu不釋放,這種理解是不對的。
那麼什麼情況下的核心繁忙才會引起soft lockup呢?
實際上,當我們禁止排程或者持有自旋鎖之後,執行了乙個很耗時的任務,那麼就很可能會觸發該問題,因為排程被關閉以後,cpu就歸當前的程序所有了,watchdog執行緒也就無法得到排程了。
關於持有自旋鎖後執行繁忙任務的場景,讀者可能會覺得這一條應該被歸於第一種場景。因為程序持有的鎖在其他程序嘗試獲取時就相當於發生了死鎖,那麼就變成了第一種場景,不過我寫在這裡實際上是考慮的另一種情況:長時間持有自旋鎖。
假如有程序a進入核心態後持有了spinlock,並執行了繁重的任務,需要耗時很長,並且一直也沒有其他程序去獲取該鎖,那麼它同樣會因為核心繁忙而導致soft lockup。這裡的關鍵就是spinlock暗含了關閉搶占的操作,導致持有鎖的cpu上,watchdog執行緒無法被排程執行。
另乙個例子:在numa系統中,對於乙個共享變數的訪問,如果採用了讀寫鎖,有大量讀者時,可能導致寫鎖一直獲取不到,特別是numa系統中不同cpu對記憶體的訪問時間也不同。
再比如:核心持有鎖的情況下執行了大量物件的掃瞄、釋放、申請動作等等。
第三種:虛擬機器中資源獲取受限
筆者是在雲廠商工作,所以第三種呢,考慮到的是虛擬機器場景, 通過redhat提供的一些案例中可知,如果發生soft lockup的地方是很隨機沒有規律的,並且有一些地方**上看是不可能發生soft lockup的地方,那麼就需要考慮是虛擬化引入的問題,對於物理機器來說,乙個soft lockup很可能是核心的bug或者硬體的bug,而對於虛擬機器場景,還有一種可能就行虛擬化機制帶來的overcommit(especially memory overcommitment or other virtualization overheads), 比如 hypervisor not scheduling virtual cpus in timely manner。
ipi中斷超時響應
在虛擬機器場景下,對於soft lockup我遇到過多例都是soft lockup死在了ipi請求過程中,特別是函式smp_call_function_many中:
pid:
12263 task: ffff8803bbebdee0 cpu:
2 command:
"kworker/u8:0"
bt: page excluded: kernel virtual address: ffffffffffffffff type:
"cpu_online_map"
#0[ffff88043fd03cf8] machine_kexec at ffffffff8105c4cb
#1[ffff88043fd03d58] __crash_kexec at ffffffff81104a32
#2[ffff88043fd03e28] panic at ffffffff8169dc5f
#3[ffff88043fd03ea8] watchdog_timer_fn at ffffffff8112f651
#4[ffff88043fd03ee0] __hrtimer_run_queues at ffffffff810b4ae4
#5[ffff88043fd03f38] hrtimer_interrupt at ffffffff810b507f
#6[ffff88043fd03f80] local_apic_timer_interrupt at ffffffff81053895
#7[ffff88043fd03f98] smp_apic_timer_interrupt at ffffffff816b76bd
#8[ffff88043fd03fb0] apic_timer_interrupt at ffffffff816b5c1d---
---#9[ffff88000399b738] apic_timer_interrupt at ffffffff816b5c1d
[exception rip: smp_call_function_many+
514]
rip: ffffffff810f99a2 rsp: ffff88000399b7e8 rflags:
00000202
rax:
0000000000000003 rbx:
00000000000000fc rcx: ffff88043fd9adb8
rdx:
0000000000000003 rsi:
0000000000000004 rdi:
0000000000000000
rbp: ffff88000399b820 r8: ffff88017a1ee000 r9: ffffffff813227d9
r10: ffff88043fd19c80 r11: ffffea00000c2100 r12:
0000000000000292
r13: ffff88000399b798 r14: ffffea0010b1f842 r15:
0000000000000000
orig_rax: ffffffffffffff10 cs:
0010 ss:
0018
#10[ffff88000399b828] native_flush_tlb_others at ffffffff8106e668
#11[ffff88000399b878] flush_tlb_page at ffffffff8106e864
對於soft lockup發生在ipi請求過程中的案例,實際上是有乙個固定的步驟進行排查的,一般都是由於傳送ipi請求的一方傳送請求後,一直在忙等待請求函式的執行完成,而執行cpu一直沒有正常執行該函式導致了soft lockup。對於這類問題首先需要找到導致soft lockup的cpu上的堆疊,根據堆疊資訊查詢到函式的入口引數,一般包括目標cpu和對應的csd結構體,通過這兩個資訊來確定哪個cpu在執行請求,檢視對應cpu上的堆疊以及執行佇列,從而確認該cpu是否處於繁忙狀態,以及當前在執行什麼操作。通過這兩點確定是否可能造成死鎖或者長時間無響應的情況。
參考
grttimeofday和xtime的定時精度
客戶反映,gettimeofday獲取的時間us部分總是零。自己修改測試 有如下結果 lpc3250test 1 0 50000 divsor is 1 sec is 0 usec is 50000 current time sec 1289836976 usec 390000 current ti...
grttimeofday和xtime的定時精度
客戶反映,gettimeofday獲取的時間us部分總是零。自己修改測試 有如下結果 lpc3250test 1 0 50000 divsor is 1 sec is 0 usec is 50000 current time sec 1289836976 usec 390000 current ti...
stdin,stdout,stderr和重定向
c程式自動開啟3個檔案,標準輸入,標準輸出和標準錯誤輸出。預設情況下分別指向鍵盤,顯示器,顯示器。這裡的檔案指的是指向file的指標。file是stdio.h中定義的一種派生型別。file型別指標,指向乙個關於檔案資訊的資料報,其中包括檔案i o使用的緩衝區的資訊。stdin,stdout,stde...