用
LINUX
也有一段時間了
,
一直用
gtk,
看到
glib
下面有
gsignal,
在
linux
下面又有
signal
定義的訊號回調之類的
,
看起來很像
,
但是又不怎麼像
,
感覺有點模糊這之間到底有何關係呢?花了時間看了一下稍微總結一下
:
1.
他們之間無必然聯絡
,gsignal
是
glib
自訂一套訊號集合系統
,
所謂的這個系統是運行在使用者態
,
完全不會執行核心的環境切換,而且你可以理解成
,
同步回調。而
signal
是核心支援的
64
種事件的系統調用
,
所謂系統調用則一旦發生會進入核心去尋找相應需要發送的進程去通知他們進行回調註冊。
2.
為什麼
signal
定義的叫事件
,gsignal
定義的叫訊號?
在這裡事件一般認為是外部觸發的
,
能夠喚醒進程進行調度的
,
而訊號則不具備這樣能力
,
只是內部回調實現的一個機制命名為訊號。這裡所說均特指
glib
中。在
glib
中
mainloop
在迴圈監測事件,其實並不監測
signal
,因為
signal
一旦
emit
將直接存取全域
signal
鏈表尋找匹配的回調直接調用了,而無機會進入
loop
迴圈。
3.
那所謂的非同步監測事件是什麼,是
glib
本身提供對系統
signal
的封裝,就是說他支援外來事件隊列,就是監測一個
FD
上的
IO
操作之類,然後一旦
glib
本身捕獲到這個事件後,解析一下打包成標準的
gsignal
訊號發送,非同步是非同步在捕獲外來事件這個層面,而不在
gsignal
的發送上。
4.
那到底
gsignal
發送和
signal
發送有什麼不一樣,其實實現過程就是原理大致相同,把訊號放到隊列中,然後檢測是否可以發送,而後回調指定的回調。但是要區別的是
gsignal
運行在使用者空間,而
signal
運行在核心空間,雖然原理一樣,但是一旦回調註冊的回呼函數,那就是完全不同的,
gsignal
因為在同一個進程下會直接知道地址進行調用,而
signal
不行只能通過中斷喚醒相應進程還要壓入參數等等進行回調。
Gsignal
使用二叉樹行進排列
signal
節點因為
signalid
也是一個
int
資料依次遞增,使用二叉樹尋找排序的消耗比較穩定一些。而
signal
應該並沒有用特殊的資料結構,它只是與進程緊密綁定,所有進程包含一個
signal
等相關結構體來標誌目前監控那些訊號,
block
了那些訊號,還有其訊號的回調是否預設或者
ignore
還是使用者調用等等等等狀態,而且普通的訊號不能被多次
pending
就是說訊號不能沒有調用就又產生了。
5.
說下
signal
發送過程,其實系統事件處理分為兩步
generate
,
delivery
,產生階段只是在核心相應的進程的
signal
的結構中標誌一下我有這個訊號需要處理就跑路了,而發送階段一般在後面系統調用發送後核心會檢測進程裡面是否有訊號準備完畢了可以滿足條件發送了?滿足了就進行中斷進入使用者空間調用。在這中間要射沒射的就是
pending
狀態,你只能搞完了才能來接活工作。
Rt
處理則不一樣,這個不在討論只列。而
gsignal
也有
pending
列表,這個什麼狀況原來不是說訊號發送是同步的嗎?還需要嘛個鏈表緩衝資訊啊,實際情況是
pending
我認為是由外來事件觸發引起的,因為外來事件觸發後如果沒機會執行,只能訊息片緩衝在那邊,等到工作忙完了一看已經有好多事件在那邊了,怎麼辦?那就進行緩衝按照優先順序進行排隊。進入
loop
迴圈一個一個調用
pending
的裡面的事件進行處理。雖然
gsignal
也處理外來事件,我認為其處理還有封裝自己的一些業務在裡面並不是說一來就直接回調了,得按照
gsignal
統一得設計來做,排隊,按優先順序一個一個做。不忙那就另當別論。