業務多線程進程 (用戶態) 掛死,OS 反應遲鈍,top 顯示大量線程 R 狀態、CPU 97% us、每線程 ~10% CPU,核心堆疊卡在 retint_careful。本文完整記錄從核心堆疊分析、調度統計、用戶態 GDB 附掛定位死循環的排查鏈路。
top:85 running threads,Cpu(s): 97.6%us, 2.2%sy,負載 84+。z_itask_templat,PID 群聚,CPU 均勻分佈 (~10%/thread)。cat /proc/PID/task/TID/stack 全卡在 retint_careful+0x14/0x32。retint_careful 為 x86_64 中斷返回路徑,關鍵邏輯:
bt $TIF_NEED_RESCHED, %edx
jnc retint_signal
TRACE_IRQS_ON
ENABLE_INTERRUPTS
pushq_cfi %rdi
SCHEDULE_USER # 呼叫 schedule()
popq_cfi %rdi
...
jmp retint_check
堆疊卡在 SCHEDULE_USER 表示:**用戶態進程被中斷打斷,返回時發現需要調度 (TIF_NEED_RESCHED),進入排程器**。
汇编直接呼叫 schedule(),未建立標準堆疊幀 (無 push %rbp、mov %rsp,%rbp),故 perf//proc/stack 看不到。
cat /proc/PID/task/TID/schedstat
# 輸出三欄:sum_exec_runtime, sum_sleep_runtime, nr_switches
# 連續觀測三值持續遞增 → 線程持續獲得 CPU 時間片 → 用戶態非睡眠忙碌
大量同優先級線程 + CFS 調度器 → 時間片均分,無單線程獨佔。
業務線程優先級普通 (SCHED_OTHER),不影響最高優先級 watchdog 核心線程調度,故無 softlockup。
中斷返回是**調度發生的天然點**;我們用 cat /proc/stack 觀測時,觀測進程本身獲得調度,正好在中斷返回路徑 → 必然看到此堆疊。
-g -O0 保留除錯資訊。gdb -p PID 附掛目標進程。info threads 列出所有線程。thread apply all bt 取得所有線程用戶態堆疊。while(1) 無退出條件、鎖未釋放導致自旋等)。| 模式 | 特徵 | 排查重點 |
|---|---|---|
| 純計算死循環 | CPU 100% us,無系統呼叫 | 堆疊停在業務計算函式 |
| 自旋鎖爭用 | CPU 高、futex 系統呼叫頻繁 | 檢查鎖範圍、條件變數 |
| 非阻塞輪詢 | epoll/poll timeout=0 狂呼叫 | 檢查事件迴圈邏輯 |
| 記憶體分配失敗重試 | malloc 失敗無限重試 | 檢查 OOM、記憶體洩漏 |
sched_yield() 或 usleep() 釋放 CPU。top -H 線程級 CPU,設定告警閾值 (如單線程 > 80% 持續 5 分鐘)。-fno-omit-frame-pointer 保留幀指標,利於 perf/GDB 回溯。ulimit -c unlimited、/proc/sys/kernel/core_pattern) 供事後分析。
Gentoo 升級後 libpng 1.5 導致編譯失敗:gda、opencv、wxPython 修復實戰
建立 Swap 交換檔並設定開機自動掛載:dd 建立、mkswap 格式化、rc.local 加入啟動
Linux 建立 RPM 套件完整流程:目錄結構、Spec 檔編寫、打包與安裝驗證
Ubuntu Live CD 修復 Grub 引導完整教學:解決雙系統啟動故障
Linux 磁碟與檔案管理核心指令大全:從裝置命名到分區實戰
Linux 新手必學 10 大基礎指令:pwd、cd、ls、cat、grep、touch、cp、mv、rm、rmdir