2015-09-23 36 views
1

我正在開發嵌入式Linux系統(3.12.something),而且我們的應用程序在經過一段隨機時間後開始佔用中央處理器。我對我們的應用程序運行strace,當問題發生吧,我看到很多在strace輸出類似於這樣的行:如何從strace輸出中確定我的程序的哪部分未能獲得互斥鎖

[48530666] futex(0x485f78b8, FUTEX_WAIT_PRIVATE, 2, NULL) = -1 EAGAIN (Resource temporarily unavailable) <0.009002> 

我敢肯定,這是確鑿的證據,我尋找和有某種比賽。然而,我現在需要弄清楚如何確定代碼中試圖獲得這個互斥體的地方。我怎樣才能做到這一點?我們的代碼是用GCC編譯的,並且有調試符號。

我目前的想法(我還沒有嘗試過)是打印出一個字符串輸出到stdout和flush之前試圖抓住我們系統中的任何互斥體,期望在strace抱怨獲得字符串之前,鎖......但代碼中有很多地方需要這樣安裝。

編輯:我剛剛意識到的另一個奇怪的事情是,我們的程序不會開始佔用CPU,直到運行一段隨機時間(5分鐘到5小時以及之間的任何地方)。在此期間,有futex系統調用發生。他們爲什麼突然開始?從我讀過的東西,我想也許他們正在用戶空間中正確使用,直到出現故障並回退到製作futex()系統調用...

有什麼建議嗎?

+2

只有競賽鎖可見,您可以嘗試與gdb合作。 strace確實有一個線程輸出切換以及由pid給出strace輸出。 –

+0

我將如何使用gdb來找到它?它能否以某種方式檢測到這種情況並自動中斷? (我不想看到幾個小時的問題開始......) – Steve

+0

好吧,它看起來像'catch syscall 240'將在gdb中工作。我會給你一個鏡頭。 – Steve

回答

0

如果您永久且經常地鎖定來自不同線程的短時間的互斥鎖,例如,一個保護全局記錄器,你可能會導致一個所謂的線程車隊。直到兩個線程競爭鎖定,問題纔會發生。第一個獲得鎖並持有一段時間,然後,當它再次需要鎖時,它會被搶佔,因爲第二個鎖已經在等待。第二個也是一樣的。每個線程可用的時間片突然減少到兩次鎖定嘗試之間的時間,導致許多上下文切換和相應的減速。此外,除了一個線程外,其他所有線程總是在互斥鎖上被阻塞,從而有效地禁止任何並行執行。

爲了解決這個問題,讓你的線程合作,而不是爭奪資源。對於上述記錄器的例子,可以考慮例如用於條目的無鎖隊列或使用線程本地存儲的每個線程的單獨隊列。

關於futex()調用,這個想法是輪詢原子標誌,並在一些旋轉後使用實際的操作系統互斥體。原子標誌在用戶空間和內核空間之間沒有昂貴的切換時可用。對於更長的休息時間,使用內核搶佔(使用futex())可避免使用輪詢阻塞CPU。這解釋了爲什麼該程序在正常操作中不需要任何futex()調用。

0

你,這時基本上需要生成核心文件。

然後,你可以在GDB加載程序+核心,看看它

man gcore

generate-core-file

在此期間,還有零futex的系統調用發生。他們爲什麼突然開始?

這是由於通過futex實現的無爭議互斥體不會進行系統調用,而只是原子增量,純粹是在用戶空間中。系統調用