[英]POSIX Threads/Signals: Portable way to determine to which thread a signal was delivered?
[英]POSIX threads and signals
- 什么是控制信號傳遞到哪個線程的最佳方法?
正如@ zoli2k所指出的那樣,明確地指定一個線程來處理你想要處理的所有信號(或者每個具有特定信號職責的一組線程),這是一種很好的技術。
- 告訴另一個線程(可能實際上很忙)信號已經到達的最佳方法是什么?[...]
- 如何安全地處理將信號發生的信息傳遞給其他線程? 這是否需要在信號處理程序中發生?
我不會說“最好”,但這是我的建議:
在main
阻止所有所需信號,以便所有線程都繼承該信號掩碼。 然后,將特殊信號接收線程設計為信號驅動事件循環,將新到達的信號作為一些其他線程內通信進行分派。
最簡單的方法是讓線程使用sigwaitinfo
或sigtimedwait
在循環中接受信號。 然后線程以某種方式轉換信號,可能廣播pthread_cond_t
,喚醒具有更多I / O的其他線程,在特定於應用程序的線程安全隊列中排隊命令,無論如何。
或者,特殊線程可以允許將信號傳遞到信號處理程序,僅在准備好處理信號時取消屏蔽以便傳送。 (然而,通過處理程序傳遞信號往往比通過sigwait
系列接收信號更容易出錯。)在這種情況下,接收器的信號處理程序執行一些簡單且異步信號安全的操作:設置sig_atomic_t
標志,調用sigaddset(&signals_i_have_seen_recently, latest_sig)
, write
一個字節write
一個非阻塞的自管道等等。然后,回到其屏蔽的主循環中,線程將信號的接收傳遞給其他線程,如上所述。
( 更新 @caf正確地指出sigwait
方法是優越的。)
根據POSIX標准,所有線程應該在系統上顯示相同的PID,並且使用pthread_sigmask()
可以為每個線程定義信號阻塞掩碼。
由於允許每個PID只定義一個信號處理程序,我更喜歡處理一個線程中的所有信號,如果需要取消正在運行的線程,則發送pthread_cancel()
。 它是針對pthread_kill()
的首選方法,因為它允許為線程定義清理函數。
在一些較舊的系統上,由於缺乏適當的內核支持,正在運行的線程可能與父線程的PID具有不同的PID。 有關在Linux 2.4上使用linuxThreads進行信號處理的常見問題解答。
恕我直言,Unix V信號和posix線程混合不好。 Unix V是1970.POSIX是1980;)
有取消點,如果你在一個應用程序中允許信號和pthreads,你最終會在每個調用周圍編寫循環,這可能會令人驚訝地返回EINTR。
所以我在(少數)我需要在Linux或QNX上編程多線程的情況下做的是,屏蔽所有(但是一個)線程的所有信號。
當Unix V信號到達時,進程切換堆棧(這是Unix V中的並發性,就像在進程中一樣)。
正如這里提到的其他帖子所暗示的,現在可能告訴系統哪個posix線程應該是該堆棧切換的受害者。
有一次,你設法讓你的信號處理程序線程工作,問題仍然存在,如何將信號信息轉換為文明的東西,其他線程可以使用。 需要用於線程間通信的基礎結構。 一種模式,有用的是actor模式,其中每個線程都是某些進程內Messaging機制的目標。
因此,您應該嘗試將信號從Signal上下文編組到Signal處理程序線程,然后使用actor模式通信機制向這些actor發送語義上有用的消息,而不是取消其他線程或殺死它們(或其他奇怪的東西),誰需要信號相關的信息。
到目前為止我在哪里:
我仍然需要對signal
與sigaction
, pselect
, sigwait
, sigaltstack
以及一大堆其他POSIX(和非POSIX)API進行排序。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.