首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> C >> 關於C

Linux 多執行緒環境下:信號究竟發給誰?

     編輯:關於C

前言

在 Linux 中,行程與執行緒在核心層級皆以 task_struct 表示,均由 do_fork 建立,僅參數不同。若行程只有一條執行緒,信號自然發給該執行緒;但當行程擁有多條執行緒時,信號處理函數屬於行程資源,信號究竟會遞送給哪一條執行緒?本文透過三個實驗探討此問題。

實驗環境

  • OS: Fedora 11
  • Kernel: 2.6.29.4-167.fc11.i686.PAE
  • GCC: 4.4.0
  • 編譯指令: gcc -g -W -Wall -Wextra -o mytest main.c -lpthread

實驗一:終端產生的信號 (SIGINT, SIGQUIT)

程式碼重點:主執行緒註冊 SIGQUIT 處理器,子執行緒註冊 SIGINT 處理器。兩執行緒皆進入 pause() 等待信號。

// 主執行緒
sigaction(SIGQUIT, &sa, 0);
// 子執行緒
sigaction(SIGINT, &sa, 0);

結果:無論在終端輸入 Ctrl-C (SIGINT) 或 Ctrl-\\ (SIGQUIT),信號**皆發送給主執行緒** (TID 2536)。

^CC
2536 recv signal: Interrupt
I'm Zuro 2536
^\ 
2536 recv signal: Quit
I'm Zuro 2536

實驗二:硬體例外信號 (SIGSEGV)

修改:主執行緒註冊 SIGSEGV 處理器;子執行緒故意解參考空指標產生 SIGSEGV。

結果:信號**發送給產生錯誤的子執行緒**,而非主執行緒。

實驗三:執行緒主動發送信號

修改:主執行緒註冊 SIGQUIT 處理器;子執行緒呼叫 raise(SIGQUIT) 產生信號。

結果:信號**發送給呼叫 raise 的子執行緒**。

結論總結

若信號由本行程產生 (如 raise、硬體例外),則遞送給產生該信號的執行緒;
若信號由其他行程產生 (如終端、kill),則遞送給主執行緒。

完整實驗程式碼

三個實驗的完整 main.c 原始碼已包含於原文中,關鍵差異在於 sigaction 註冊的信號與信號產生方式。讀者可自行編譯驗證。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved