棧類型對比
| 棧類型 | 位置/屬性 | 大小 | 用途 | 切換時機 |
| 用戶態棧 | 進程虛擬地址空間底部 | 默認 8MB (ulimit -s) | 用戶態函數調用、局部變量 | 進程調度、系統調用進入/返回 |
| 內核棧 | 內核地址空間,與 thread_info 共用 thread_union | 默認 8KB (可配置) | 系統調用、中斷處理、內核函數調用 | 用戶態↔內核態切換時自動切換 |
| 中斷棧 | 每 CPU 一個,默認共用內核棧頁框 | 1 頁 (4KB) | 硬中斷、軟中斷、異常處理 | 中斷發生時自動切換 |
內核棧結構
union thread_union {
struct thread_info thread_info;
unsigned long stack[THREAD_SIZE/sizeof(long)];
};
- 放在特殊段
__section(".data.init_task")
- 初始進程棧:
init_thread_union
- 棧頂地址:
stack_start = init_thread_union + THREAD_SIZE
- 屬於進程私有,每個進程/線程獨立擁有
中斷棧特點
- 默認與內核棧共享內存頁框,但邏輯獨立、內容不共見
- 中斷上下文使用,避免中斷嵌套溢出內核棧
- 可通過內核配置
CONFIG_HARDIRQS_STACK、CONFIG_SOFTIRQS_STACK 獨立分配
切換流程
- 系統調用:用戶態 → 內核態,CPU 自動切換到當前進程的內核棧(
SS0:ESP0 來自 TSS)
- 中斷:若發生在用戶態,同系統調用切到內核棧;若在內核態,可能切換到中斷棧(取決於配置)
- 返回:
iret/sysret 恢復用戶態棧指針
排查技巧
cat /proc/PID/stack 查看進程內核棧回溯
- 內核棧溢出導致 Oops,常見於深度遞歸、大局部數組
- 中斷棧溢出極難調試,建議啟用獨立中斷棧配置