2011-12-13 120 views
8

我在一個情況下,我需要閱讀的信號處理器(SIGSEGV信號處理程序,據我所知這是每個線程基地)內的二叉搜索樹(BST)內共享數據。 BST可以由應用程序中的其他線程修改。讀信號處理程序

現在既然信號處理程序不能使用信號量,互斥鎖等,因此無法訪問共享數據,我該如何解決這個問題?請注意,我的應用程序是多線程並在多核系統上運行。

+5

我會努力想辦法不讀取該信號處理程序中的共享數據。 – dbeer

+1

爲了強調@dbeer的要點,在信號處理程序中,您通常不應該做任何會阻止或引發其他信號或任何冗長操作的任何操作。信號處理程序應該很小,很快且很短。 –

+1

也許我錯過了一些東西,但是如果只有程序的線程訪問共享內存(沒有其他中斷和異常),爲什麼不使用信號量(不管它是不錯的風格是一個不同的問題)?如果一個線程訪問關鍵區域,阻塞它,被另一個線程休眠,信號量仍然被鎖定爲另一個線程,並且最終您的初始線程將被安排再次訪問它。除了性能方面的原因,我認爲既沒有數據損壞的危險,也沒有拖延系統。 – gnometorule

回答

3

假設SH不能直接訪問共享數據,那麼也許你可以做到這一點間接:

  1. 具有唯一信號處理程序可以編寫一些全局變量,但可以從其他地方讀取(甚至如果只在同一個線程內)。
  2. SH在被調用時設置標誌
  3. 線程輪詢該標誌,當它們不在修改BST時;當找到它時,它們進行原始信號所需的處理(使用任何需要的同步),然後產生一個不同的信號(如SIGUSR1)來表示處理已完成
  4. SH THAT信號復位標誌

如果你擔心重疊SIGSEGVs,計數器加進來跟蹤。 (嘿!你剛剛建立了你自己的信號量!)

這裏的薄弱環節顯然是輪詢,但它是一個開始。

+0

我在想同樣的事情:-p!但是當一個線程在信號發生時修改BST會發生什麼。這一點有點令人擔憂。 – MetallicPriest

+0

我認爲這不會是一個問題:信號會被抓住,設置標誌並返回;該線程將繼續修改BST,並且不會嘗試「處理」信號,直到完成修改爲止。假設這種修改是原子的,那看起來是一個合理的結果。 –

1

您可能會考慮mmap -ing a fuse文件系統(在用戶空間中)。

其實,你會在Gnu Hurd更幸福這對於external pagers

或許你在你的信號處理函數讀二叉搜索樹砍支持往往可以在實際工作中,非便攜和內核版本依賴的方式。也許序列化訪問與低級別的非便攜式技巧(例如futexesatomic gcc builtins)可能工作。閱讀NPTL(特定機器)的源代碼,即當前的Linux pthread例程應該有所幫助。

這可能是pthread_mutex_lock等實際上可以從Linux信號處理程序中使用的情況......(因爲它可能只有futex和原子指令)。

+0

我提到了一些非移動技巧和Gnu赫德... –

3

我可以看到兩個很乾淨的解決方案:

  1. Linux特有:創建一個專用線程處理的信號。使用signalfd()捕獲信號。這樣你將在普通線程中處理信號,而不是任何有限的處理程序。
  2. 便攜式:還使用專用線程睡眠,直到收到信號。您可以使用管道來創建一對文件描述符。線程可以從第一個描述符讀取(2),並在一個信號處理程序中讀取(2)到第二個描述符。根據POSIX,在信號處理程序中使用write()是合法的。當線程從管道讀取某些內容時,它知道它必須執行一些操作。