4.2.3、epoll:水平觸發(fā)與邊緣觸發(fā)

select和poll都只提供了一個函數(shù):select或者poll函數(shù)。
而epoll提供了三個函數(shù),epoll_create,epoll_ctl和epoll_wait,epoll_create是創(chuàng)建一個epoll句柄;epoll_ctl是注冊要監(jiān)聽的事件類型;epoll_wait則是等待事件的產(chǎn)生。

epoll除了提供select/poll那種IO事件的水平觸發(fā)(Level Triggered)外,還提供了邊緣觸發(fā)(Edge Triggered),這就使得用戶空間程序有可能緩存IO狀態(tài),減少epoll_wait/epoll_pwait的調(diào)用,提高應(yīng)用程序效率。

水平觸發(fā)(level-trggered)

只要文件描述符關(guān)聯(lián)的讀內(nèi)核緩沖區(qū)非空,有數(shù)據(jù)可以讀取,就一直發(fā)出可讀信號進行通知,
當文件描述符關(guān)聯(lián)的內(nèi)核寫緩沖區(qū)不滿,有空間可以寫入,就一直發(fā)出可寫信號進行通知
LT模式支持阻塞和非阻塞兩種方式。epoll默認的模式是LT。

邊緣觸發(fā)(edge-triggered)

當文件描述符關(guān)聯(lián)的讀內(nèi)核緩沖區(qū)由空轉(zhuǎn)化為非空的時候,則發(fā)出可讀信號進行通知,
當文件描述符關(guān)聯(lián)的內(nèi)核寫緩沖區(qū)由滿轉(zhuǎn)化為不滿的時候,則發(fā)出可寫信號進行通知
兩者的區(qū)別在哪里呢?水平觸發(fā)是只要讀緩沖區(qū)有數(shù)據(jù),就會一直觸發(fā)可讀信號,而邊緣觸發(fā)僅僅在空變?yōu)榉强盏臅r候通知一次,

LT(level triggered)是缺省的工作方式,并且同時支持block和no-block socket.在這種做法中,內(nèi)核告訴你一個文件描述符是否就緒了,然后你可以對這個就緒的fd進行IO操作。如果你不作任何操作,內(nèi)核還是會繼續(xù)通知你的,所以,這種模式編程出錯誤可能性要小一點。傳統(tǒng)的select/poll都是這種模型的代表.

水平觸發(fā)和邊緣觸發(fā)模式區(qū)別

  1. 讀緩沖區(qū)剛開始是空的
  2. 讀緩沖區(qū)寫入2KB數(shù)據(jù)
  3. 水平觸發(fā)和邊緣觸發(fā)模式此時都會發(fā)出可讀信號
  4. 收到信號通知后,讀取了1kb的數(shù)據(jù),讀緩沖區(qū)還剩余1KB數(shù)據(jù)
  5. 水平觸發(fā)會再次進行通知,而邊緣觸發(fā)不會再進行通知
    所以,邊緣觸發(fā)需要一次性的把緩沖區(qū)的數(shù)據(jù)讀完為止,也就是一直讀,直到讀到EGAIN為止,EGAIN說明緩沖區(qū)已經(jīng)空了,因為這一點,邊緣觸發(fā)需要設(shè)置文件句柄為非阻塞
//水平觸發(fā)
ret = read(fd, buf, sizeof(buf));

//邊緣觸發(fā)
while(true) {
    ret = read(fd, buf, sizeof(buf);
    if (ret == EAGAIN) break;
}

設(shè)置方法

int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);
epoll的事件注冊函數(shù),它不同與select()是在監(jiān)聽事件時告訴內(nèi)核要監(jiān)聽什么類型的事件,而是在這里先注冊要監(jiān)聽的事件類型。

第一個參數(shù)是epoll_create()的返回值,

第二個參數(shù)表示動作,用三個宏來表示:
EPOLL_CTL_ADD:注冊新的fd到epfd中;
EPOLL_CTL_MOD:修改已經(jīng)注冊的fd的監(jiān)聽事件;
EPOLL_CTL_DEL:從epfd中刪除一個fd;

第三個參數(shù)是需要監(jiān)聽的fd,第四個參數(shù)是告訴內(nèi)核需要監(jiān)聽什么事,struct epoll_event結(jié)構(gòu)如下:
struct epoll_event {
__uint32_t events; /* Epoll events /
epoll_data_t data; /
User data variable */
};

events可以是以下幾個宏的集合:
EPOLLIN :表示對應(yīng)的文件描述符可以讀(包括對端SOCKET正常關(guān)閉);
EPOLLOUT:表示對應(yīng)的文件描述符可以寫;
EPOLLPRI:表示對應(yīng)的文件描述符有緊急的數(shù)據(jù)可讀(這里應(yīng)該表示有帶外數(shù)據(jù)到來);
EPOLLERR:表示對應(yīng)的文件描述符發(fā)生錯誤;
EPOLLHUP:表示對應(yīng)的文件描述符被掛斷;
EPOLLET: 將EPOLL設(shè)為邊緣觸發(fā)(Edge Triggered)模式,這是相對于水平觸發(fā)(Level Triggered)來說的。
EPOLLONESHOT:只監(jiān)聽一次事件,當監(jiān)聽完這次事件之后,如果還需要繼續(xù)監(jiān)聽這個socket的話,需要再次把這個socket加入到EPOLL隊列里。

使用示例

使用ET的例子:nginx
使用LT的例子:redis

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 1.《學(xué)會提問》和《提問的藝術(shù)》在不問開智群的情況下,如何確定哪本是開智大典的內(nèi)容?答案:開智大典的意義在于讀經(jīng)典...
    牛牛牛牛牛魔王閱讀 455評論 0 16
  • 這是一首講述悲切愛情故事的情歌,告訴大家別相信太多,別愛太多,別希望太多,因為這些太多最終會讓你傷的太多。每個...
    小機靈鬼_閱讀 564評論 0 3
  • 突然看到這個app,希望每天可以在這里寫點什么,又沒有誰能看到寫的是什么,也希望我能堅持養(yǎng)成一個好習(xí)慣吧。 很多時...
    wdsprite閱讀 254評論 0 0
  • 今天挑戰(zhàn)用黑卡繪畫: 沒有黑磚,用櫻花高光筆在黑紙上繪畫,也沒有白色鉛筆,用白色彩鉛代替了。全黑的底色,猶如潑墨一...
    小小鳥028閱讀 330評論 3 4

友情鏈接更多精彩內(nèi)容