在linux的io多路復用中有水平觸發,邊緣觸發兩種模式,這兩種模式的區別如下:
水平觸發:如果檔案描述符已經就緒可以非阻塞的執行io操作了,此時會觸發通知.允許在任意時刻重複檢測io的狀態,沒有必要每次描述符就緒後盡可能多的執行io.select,poll就屬於水平觸發.
邊緣觸發:如果檔案描述符自上次狀態改變後有新的io活動到來,此時會觸發通知.在收到乙個io事件通知後要盡可能多的執行io操作,因為如果在一次通知中沒有執行完io那麼就需要等到下一次新的io活動到來才能獲取到就緒的描述符.訊號驅動式io就屬於邊緣觸發.
epoll既可以採用水平觸發,也可以採用邊緣觸發.
大家可能還不能完全了解這兩種模式的區別,我們可以舉例說明:乙個管道收到了1kb的資料,epoll會立即返回,此時讀了512位元組資料,然後再次呼叫epoll.這時如果是水平觸發的,epoll會立即返回,因為有資料準備好了.如果是邊緣觸發的不會立即返回,因為此時雖然有資料可讀但是已經觸發了一次通知,在這次通知到現在還沒有新的資料到來,直到有新的資料到來epoll才會返回,此時老的資料和新的資料都可以讀取到(當然是需要這次你盡可能的多讀取).
下面我們還從電子的角度來解釋一下:
水平觸發:也就是只有高電平(1)或低電平(0)時才觸發通知,只要在這兩種狀態就能得到通知.上面提到的只要有資料可讀(描述符就緒)那麼水平觸發的epoll就立即返回.
邊緣觸發:只有電平發生變化(高電平到低電平,或者低電平到高電平)的時候才觸發通知.上面提到即使有資料可讀,但是沒有新的io活動到來,epoll也不會立即返回.
邊緣觸發(edge-triggered)et:
每當狀態變化時,觸發乙個事件。
「舉個讀socket的例子,假定經過長時間的沉默後,現在來了100個位元組,這時無論邊緣觸發和條件觸發都會產生乙個read ready notification通知應用程式可讀。應用程式讀了50個位元組,然後重新呼叫api等待io事件。這時水平觸發的api會因為還有50個位元組可讀,從而立即返回使用者乙個read ready notification。而邊緣觸發的api會因為可讀這個狀態沒有發生變化而陷入長期等待。因此在使用邊緣觸發的api時,要注意每次都要讀到socket返回ewouldblock為止,否則這個socket就算廢了。而使用條件觸發的api 時,如果應用程式不需要寫就不要關注socket可寫的事件,否則就會無限次的立即返回乙個write ready notification。大家常用的select就是屬於水平觸發這一類,長期關注socket寫事件會出現cpu 100%的毛病。
[plain]
view plain
copy
lxg@remoter:~/station$ ./t_select
ni hao ma ,wo hen hao a ,ni ne ???
ni hao ma
,wo hen
hao a ,ni
ne ???
^c
[plain]
view plain
copy
lxg@remoter:~/station$ ./demo_sigio
loop 0
sigio recv:this is
loop 1
sigio recv: loop 0
loop 2
sigio recv:this is
sigio recv: loop 1
^c
水平觸發和邊緣觸發的區別
水平觸發 level triggered,也被稱為條件觸發 lt 只要滿足條件,就觸發乙個事件 只要有資料沒有被獲取,核心就不斷通知你 邊緣觸發 edge triggered et 每當狀態變化時,觸發乙個事件 舉個讀socket的例子,假定經過長時間的沉默後,現在來了100個位元組,這時無論邊緣觸...
水平觸發和邊緣觸發的區別
水平觸發 level triggered,也被稱為條件觸發 lt 只要滿足條件,就觸發乙個事件 只要有資料沒有被獲取,核心就不斷通知你 邊緣觸發 edge triggered et 每當狀態變化時,觸發乙個事件 舉個讀socket的例子,假定經過長時間的沉默後,現在來了100個位元組,這時無論邊緣觸...
邊緣觸發和水平觸發的區別
只要檔案描述符關聯的讀核心緩衝區非空,有資料可以讀取,就一直發出可讀訊號進行通知,當檔案描述符關聯的核心寫緩衝區不滿,有空間可以寫入,就一直發出可寫訊號進行通知 lt模式支援阻塞和非阻塞兩種方式。epoll預設的模式是lt。當檔案描述符關聯的讀核心緩衝區由空轉化為非空的時候,則發出可讀訊號進行通知,...