2012-12-18 51 views
2

我正在使用Unix上的C++。信號處理程序和本地狀態

說我有一個長時間運行的函數來執行某些操作,例如從文件中讀取數據並解析它。在這個函數中,我將從文件中讀取的東西保存在局部變量num_read中。

我想在自定義信號處理程序中捕獲CTRL + c並打印num_read的值。

我能想到的唯一方法是在堆上分配num_read並將其地址存儲在可由我的信號處理程序訪問的全局變量中。有沒有更優雅的方式?

+0

你有什麼Unix? – zaufi

+0

OS X和Debian。 – adrianN

回答

2

答案是否定的。有沒有 之間的信號處理程序和除全局 變量之外的其餘代碼之間進行通信的方式。

此外,您只能在 信號處理程序中執行非常非常有限數量的操作。例如,您不能在std::ostream, 上使用<<,也不能使用printf。在Unix下處理信號的 的通常方式是在單獨的 線程中捕獲它們。替代方案(也適用於其他操作系統)爲 ,用於定義全局變量sig_atomic_t,該變量設置在 信號處理程序中,並在主循環中輪詢。 (在你的情況, 例如,你可能每次更新 num_read時間輪詢吧)

+1

或者,對於討厭線程(我!)的unix人來說,更傳統的處理信號的方式是使用自我管道......更好!保證以及select()循環被喚醒(有一堆競爭條件與喚醒wait()循環的全局標誌方法,需要一些sigsuspend/sigprocmask雜技)。我總是推薦一種自我管道,以提高其便攜性,堅固性和完全避免所有細微問題。 –

+0

@NicholasWilson我同意線程經常被濫用,但他們確實有用。對於OP所要做的事情,sig_atomic_t標誌在很大程度上是足夠的,它甚至可以移植到非Unix系統。而當你需要做一些複雜的事情,並且沒有方便的地方進行投票時,使用單獨的線程纔是真正的唯一途徑。對於中間情況......我從來沒有聽說過從信號寫入管道,但這聽起來像是一個很好的妥協。 –

+0

unix解決信號問題的「傳統」解決方案早在線程來到unix之前,更不用說pthread了!自我管理技巧是一個絕對的經典,既非常簡單,也避免了所有的競爭條件。我當然不能寫一個基於標誌的解決方案的實現,而不檢查手冊並做一些大腦彎曲;如果信號在檢查後立即觸發,那麼主循環不會被喚醒,並且不會很快檢查標誌?另一方面,我可以在頭頂上寫一個自我管道解決方案,它確實沒有比賽和強勁。 –

2

除了傳統的Unix方式與信號處理,還有其它:

  • 因爲Linux內核2.6.22有signalfd()函數存在。您可以獲取常用文件描述符並對其進行輪詢(使用selectepoll)以獲取傳入信號。所以,當你處理一個信號沒有適當的給他們任何限制 - 它只是平常用戶空間代碼,這樣你就可以調用任何你想要的...
  • 據我知道OS X,有類似的功能目前在kqueue(搜索本網站或因特網爲EVFILT_SIGNALkqueue