您當前的位置:首頁 > 攝影

Linux中的訊號處理機制 [四]

作者:由 蘭新宇 發表于 攝影時間:2019-09-02

訊號與執行緒

Unix的訊號機制在誕生之初,生活在只有程序(process)的相對單純的環境中。自從Unix世界有了執行緒(thread)的概念,訊號就被賦予了發往程序中某個特定執行緒的能力,當然,這也增加了整個訊號機制實現的複雜度。本系列的前面三篇文章都是基於程序進行的訊號實現機制的討論,本文將著重介紹Linux中訊號和執行緒之間的互動。

傳送訊號給執行緒

無論是kill()還是sigqueue(),都只能向程序傳送訊號,在Linux中,要向程序內的執行緒傳送訊號,需要使用tkill()或者tgkill():

int

tkill

int

tid

int

sig

);

int

tgkill

int

tgid

int

tid

int

sig

);

兩個函式中,“tid”都是代表目標執行緒的PID,但tgkill()比tkill()多了一個“tgid”的引數。“tgid”是目標執行緒所在程序的PID,它可以用來防止向錯誤的執行緒傳送訊號。

傳送方給目標執行緒傳送訊號時,可能目標執行緒已經因為某種原因退出了,按照Linux中PID的分配規則,退出執行緒/程序的PID可被分配給其他的執行緒/程序使用。這種情況下,如果使用tkill(),就可能出現將訊號傳送到不相干的執行緒上。引入“tgid”可以幫助進行目標執行緒所在程序的校驗,這樣出現錯發的可能性就被大大地降低了。

執行緒對訊號的接收

根據POSIX標準的定義,程序內的所有執行緒共享程序的訊號處理函式,當程序內的一個執行緒為某個訊號註冊了處理函式,另一個執行緒可以更改這個處理函式。在Linux的實現中,執行緒作為獨立的排程實體也有自己的task_struct,同一程序的不同執行緒的task_struct的“sighand”將指向同一個包含訊號處理函式列表的sighand_struct。

Linux中的訊號處理機制 [四]

但是,每個執行緒可以有單獨的pending點陣圖/佇列和block點陣圖。如果一個訊號是傳送給執行緒的,那麼核心在遞送該訊號時,會將它放入執行緒私有的pending點陣圖/佇列中,之後根據目標執行緒的block點陣圖的設定,直接由目標執行緒處理就可以了。

Linux中的訊號處理機制 [四]

如果訊號是傳送給一個程序的,那麼該訊號在遞送時將被核心放入程序的pending點陣圖/佇列中,由程序內的所有執行緒共享。接下來,核心會從程序的各個執行緒中,挑選一個block點陣圖中沒有遮蔽該訊號的執行緒,來執行對應的訊號處理函式,其中,程序的主執行緒將被核心優先選擇。

但是有一些訊號是需要程序內的全體執行緒都做出響應的,比如前面提到的令程序聞風喪膽的SIGKILL,它一旦到來,就不會留下一個活口。

當一個執行緒即將被核心排程執行,而該執行緒私有的penging點陣圖/佇列和所在程序共享的penging點陣圖/佇列上都有待處理的訊號時,核心將優先向執行緒遞送私有的penging點陣圖/佇列上的訊號:

int

dequeue_signal

struct

task_struct

*

tsk

sigset_t

*

mask

kernel_siginfo_t

*

info

{

signr

=

__dequeue_signal

&

tsk

->

pending

mask

info

&

resched_timer

);

if

signr

{

signr

=

__dequeue_signal

&

tsk

->

signal

->

shared_pending

mask

info

&

resched_timer

);

。。。

}

作為Unix時代的產物,前面講到的sigprocmask()函式最初是用來設定程序的block點陣圖的,但是同pending點陣圖/佇列不同的是,並沒有一個所謂的執行緒共享的block點陣圖的概念,所以在多執行緒環境下,sigprocmask()的語義也就變成了設定執行緒的block點陣圖。當然,為了語義更加明顯,你可以使用POSIX執行緒庫提供的pthread_procmask()函式,兩者的引數和行為都是一樣的。

參考:

《Linux環境程式設計:從應用到核心》第6章

Understanding the Linux Kernel

第3版第11章

UNIX Internals: The New Frontiers

第4章

http://

kernel。meizu。com/linux-

signal。html

https://www。

ibm。com/developerworks/

cn/linux/l-ipc/part2/index1。html?ca=drs-

原創文章,轉載請註明出處。

標簽: 執行緒  點陣圖  程序  訊號  Linux