Epoll
` epoll `是 Linux 核心的擴展 I / O 事件通知機制。佇咧 Linux 二嬸五 . 四十四首度上場,伊設計目的旨咧取代既然有 POSIX ` select ( 二 ) ` 佮 ` poll ( 二 ) ` 系統函式,予需要大量來操作檔案描述子的程式會當發揮閣較媠的效能(比如講伊:舊的系統函式所開的時間來複雜度做 O ( n ),` epoll ` 的時間複雜度 O ( log n ))。 epoll 實現的功能佮 poll 類似,攏是監聽濟个檔案描述子上的事件。
` epoll ` 佮 FreeBSD 的 ` kqueue ` 類似,底層攏是由會組態的作業系統核心物件建構才成做,並且用檔案來講 ( file descriptor ) 的形式呈現使用者空間。` epoll ` 通過使用紅烏樹 ( RB-tree ) 搜揣被監視的檔案咧講 ( file descriptor )。
佇咧 epoll 實例上註冊事件的時陣,epoll 會去共這个事件加做伙 epoll 實例的紅烏樹頂並且註冊一个回呼函式,當事件發生的時陣會將事件添加著就緒連結串列內底。
程式介面
佇核心內底建立 ` epoll ` 實例閣返回一个 ` epoll ` 檔案描述子。 上早的實現中,呼叫者通過 ` size ` 參數告知核心需要監聽的檔案描述子數量。若監聽檔案咧講數量超過 size , 是核心會去自動擴容。這馬 size 已經無這種語意矣,但是呼叫者呼叫時 size 猶原著愛大於零,以保證後向相容性。
向 epfd 對應的核心 ` epoll ` 實例添加、修改抑是刪除嘿 fd 上事件 event 的監聽。op 會當做是 ` EPOLL _ CTL _ ADD ` , ` EPOLL _ CTL _ MOD ` , ` EPOLL _ CTL _ DEL ` 分別對應的是添加新的事件,修改檔案描述子上監聽的事件類型,對實例上刪除一个事件。若是 event 的 events 屬性設定矣 ` EPOLLET ` flag,那麼監聽該事件的方式是邊緣觸發。
當 timeout 為零時,epoll \ _ wait 永遠會隨返回。而且 timeout 為學一時仔,epoll \ _ wait 伊會一直阻擋到任一已經註冊的事件變做就緒。當 timeout 為一正整數的時陣,epoll 會阻塞到計時 timeout 毫秒終了抑是註冊的事件變做就緒。因為核心排程延遲,窒起來的時間可能會略仔超過 timeout 毫秒。
觸發模式
` epoll ` 邊仔提供沿路發佮狀態觸發模式。佇邊仔沿路發模式當中,` epoll _ wait ` 一定會佇咧新的事件第一遍被加入 ` epoll ` 在列時回回;佇咧 level-triggered 模式下,` epoll _ wait ` 佇咧事件狀態無變更前將不斷被觸發。狀態觸發模式是恬認的模式。
狀態觸發模式和那沿觸發模式有讀和寫兩款狀況,咱先來考慮讀的狀況。假使咱註冊一个讀事件到 ` epoll ` 實例上,` epoll ` 實例會通過 ` epoll _ wait ` 倒轉來值的形式通知阮佗一寡讀事件已經緒。簡單來講,佇狀態觸發模式下,若讀事件無去予人處理,該事件對應的核心讀予緩衝區非空,著愛逐擺調用 ` epoll _ wait ` 時返回的事件列表攏會包含該事件。一直到事件對應的核心讀予緩衝區為止。佇邊仔沿著發模式下,讀事件就緒後干焦會通知一改,袂反復通知。
然後阮閣考慮寫的狀況。水平觸發模式下,只要檔案來講對應的核心寫緩衝區未滿,就會一直通知會當寫事件。佇邊仔沿著發模式下,核心寫緩衝區由滿變做未滿了後,干焦會通知一改會當寫事件。
比如講伊,準若有一个已經佇咧 ` epoll ` 註冊之管線接著資料,` epoll _ wait ` 共返回,閣發出資料讀取的訊號。現假使轉衝區的資料干焦有部份予人讀取並處理,佇咧 level-triggered 模式下,任何著 ` epoll _ wait ` 之呼叫攏得欲刻返回,一直到緩衝區內底的資料全部攏予人讀;毋過,佇咧 edge-triggered 的風景之下,` epoll _ wait ` 干焦會佇再一遍接收著新的資料 ( 亦即,新資料予人寫入去管線 ) 時回倒轉。
那沿著發模式
那沿著發模式使得程式有可能佇咧使用者態緊取 IO 狀態。nginx 使用的是邊仔沿著發模式。
檔案來講是有兩種狀況是推薦使用邊沿觸發模式的。
一 . read 抑是講 write 系統呼叫回倒轉來 EAGAIN。 二 . 非常的檔案來講。
可能的缺陷:
一 . 若是 IO 空間誠大,你愛開足濟時間才會當共伊一改讀予了,這可能會做枵枵。比一个例,假使你在監聽一个檔案描述子列表,某一个檔案描述子上有大量的輸入(無停的輸入流), 啊你咧讀完伊的過程中就無閒處理其他的就緒的檔案咧描述子。(因為邊沿著發模式干焦會通知一改會當讀事件,所以你往往會想講一改共讀予了。)一種解決方案是,程式維護一个就緒在列,當 ` epoll ` 實例通知某檔案講出來就緒的時陣會佇咧就緒伊佇列的資料結構中標記做就緒,按呢程式就會記得佗一寡檔案來講等待處理。Round-Robin 迴圈處理就緒佇列中就緒的檔案描述子即可。 二 . 你若緊號所有的事件,遐爾仔一種可能的情形是 A 事件的發生予程式關起來矣另外一个檔案來講 B。但是核心的 ` epoll ` 實例並毋知影這件代誌,需要你自 ` epoll ` 刪除掉。
相關條目
- kqueue
- libevent
- I / O Completion Ports
參考資料
外部連結
- How to use epoll ? A complete example in C
- ET or LT
- epoll patch