1. 程式人生 > >水平觸發和邊緣觸發的區別

水平觸發和邊緣觸發的區別

在linux的IO多路複用中有水平觸發,邊緣觸發兩種模式,這兩種模式的區別如下:

     水平觸發:如果檔案描述符已經就緒可以非阻塞的執行IO操作了,此時會觸發通知.允許在任意時刻重複檢測IO的狀態.select,poll就屬於水平觸發.

     邊緣觸發:如果檔案描述符自上次狀態改變後有新的IO活動到來,此時會觸發通知.在收到一個IO事件通知後要儘可能多的執行IO操作,因為如果在一次通知中沒有執行完IO那麼就需要等到下一次新的IO活動到來才能獲取到就緒的描述符.訊號驅動式IO就屬於邊緣觸發.

     寫過微控制器的人可以從另一方理解水平觸發和邊緣觸發的區別:

     水平觸發:就是隻有高電平(1)或低電平(0)時才觸發通知,只要在這兩種狀態就能得到通知.上面提到的只要有資料可讀(描述符就緒)那麼水平觸發的epoll就立即返回.

 

    邊緣觸發:只有電平發生變化(高電平到低電平,或者低電平到高電平)的時候才觸發通知.上面提到即使有資料可讀,但是io狀態沒有變化epoll也不會立即返回.

    epoll既可以採用水平觸發,也可以採用邊緣觸發.

    大家可能還不能完全瞭解這兩種模式的區別,我們可以舉例說明:一個管道收到了1kb的資料,epoll會立即返回,此時讀了512位元組資料,然後再次呼叫epoll.這時如果是水平觸發的,epoll會立即返回,因為有資料準備好了.如果是邊緣觸發的不會立即返回,因為此時雖然有資料可讀但是已經觸發了一次通知,在這次通知到現在還沒有新的資料到來,直到有新的資料到來epoll才會返回,此時老的資料和新的資料都可以讀取到(當然是需要這次你儘可能的多讀取).所以當我們寫epoll網路模型時,如果我們用水平觸發不用擔心資料有沒有讀完因為下次epoll返回時,沒有讀完的socket依然會被返回,但是要注意這種模式下的寫事件,因為是水平觸發,每次socket可寫時epoll都會返回,當我們寫的資料包過大時,一次寫不完,要多次才能寫完或者每次socket寫都寫一個很小的資料包時,每次寫都會被epoll檢測到,因此長期關注socket寫事件會無故cpu消耗過大甚至導致cpu跑滿,所以在水平觸發模式下我們一般不關注socket可寫事件而是通過呼叫socket write或者send api函式來寫socket,說到這我們可以看到這種模式在效率上是沒有邊緣觸發高的,因為每個socket讀或者寫可能被返回兩次甚至多次,所以有時候我們也會用到邊緣觸發但是這種模式下在讀資料的時候一定要注意,因為如果一次可寫事件我們沒有把資料讀完,如果沒有讀完,在socket沒有新的資料可讀時epoll就不回返回了,只有在新的資料到來時,我們才能讀取到上次沒有讀完的資料。

--------------------- 本文來自 D_Guco 的CSDN 部落格 ,全文地址請點選:https://blog.csdn.net/D_Guco/article/details/71373381?utm_source=copy