epoll(2018.07.29 更新)

開始

epoll 是 Linux 提供的 I/O event notification facility。在需要監(jiān)聽的 fd 數(shù)量很多(成千上萬)而同一時刻可讀/可寫的數(shù)量又比較少(幾個韭畸?幾十個喻犁?幾百個?)的情況下上岗,性能要明顯優(yōu)于 select福荸、poll。

API

與 epoll 直接相關(guān)的 API 有:
創(chuàng)建 epoll fd:epoll_create/epoll_create1
操作 epoll fd:epoll_ctl
監(jiān)聽 epoll fd:epoll_wait/epoll_pwait

創(chuàng)建

int epoll_create(int size);
int epoll_create1(int flags);
  • epoll_create 用于創(chuàng)建一個 epoll fd肴掷。從 Linux2.6.8 開始敬锐,size 參數(shù)就被廢棄了,但是使用時傳入的參數(shù)必須大于0呆瞻。
  • epoll_create1 的參數(shù) flags 可以為 0 或 EPOLL_CLOEXEC台夺。
    • flags 為 0:epoll_create1 的作用和 epoll_create 一樣。
    • flags 為 EPOLL_CLOEXEC:將返回的 epoll fd 設(shè)置為 close on exec痴脾。

操作

int epoll_ctl(int epfd, int op, int fd, struct epoll_event* event);
  • 在 epfd 上設(shè)置 (op參數(shù)) 描述符 fd 的事件 (event 參數(shù))颤介。
  • epfd 是 epoll_create 的返回值。
  • fd 是想要操作的文件描述符赞赖。
  • op 是操作的類型滚朵,其取值有:
    • EPOLL_CTL_ADD
    • EPOLL_CTL_MOD
    • EPOLL_CTL_DEL
  • event 是 fd 所關(guān)心的事件。對于 EPOLL_CTL_DEL前域,可以傳 NULL(BUG:Linux2.6.9 之前不能傳NULL)辕近。
typedef union epoll_data {
    void* ptr;
    int fd;
    uint32_t u32;
    uint64_t u64;
} epoll_data_t;
struct epoll_event {
    uint32_t events;     // events is a bit set
    epoll_data_t data;
};
  • epoll_event 的成員 events 是一個 bit set。其值可以是下面各值的或匿垄。
    • EPOLLINT:監(jiān)聽可讀事件移宅。
    • EPOLLOUT:監(jiān)聽可寫事件。
    • EPOLLRDHUP :監(jiān)聽對端斷開連接椿疗。
    • EPOLLPRI:外帶數(shù)據(jù)漏峰。
    • EPOLLERR:Error condition happened on the associated file descriptor.
    • EPOLLHUP:Hang up happened on the associated file descriptor.
    • EPOLLET:邊沿觸發(fā),epoll 監(jiān)聽的 fd 默認是電平觸發(fā)变丧。
    • EPOLLONESHOT:對應(yīng) fd 的事件被觸發(fā)通知后芽狗,需要重新調(diào)用 epoll_ctl 對其進行修改(EPOLL_CTL_MOD),才能恢復(fù)事件觸發(fā)通知痒蓬。

監(jiān)聽

int epoll_wait(int epfd, struct epoll_event* events, int maxevents, int timeout);
int epoll_pwait(int epfd, struct epoll_event* events, int maxevents, int timeout, const sigset_t* sigmask);

監(jiān)聽的接口比較簡單童擎,暫時沒什么好介紹。

線程安全性

在知乎上看到一個問題討論 epoll 的線程安全性攻晒,里面提到 github 上的一個 issue顾复,有一段話:

One thread is calling epoll_wait() and blocks there. After that another thread is adding a new file descriptor to the epoll file. Because epoll_wait() will not take this change into consideration, it will not be woken up on that file descriptor's events.

簡單說就是,一個線程阻塞在 epoll_wait 上鲁捏,另一個線程調(diào)用 epoll_ctl設(shè)置 fd 會有問題芯砸。

但是,我在 man epoll_wait 中看到的內(nèi)容,卻說這樣做是安全的:

While one thread is blocked in a call to epoll_pwait(), it is possible for another thread to add a file descriptor to the waited-upon epoll instance. If the new file descriptor becomes ready, it will cause the epoll_wait() call to unblock.

自己簡單寫一個測試工具:一個線程負責(zé) accept TCP 連接假丧,然后調(diào)用 epoll_ctl 將新連接注冊到 epoll双揪。另一個線程負責(zé) epoll_wait,讀取 client 發(fā)送過來的數(shù)據(jù)包帚,并簡單打印出來渔期。并沒有出現(xiàn),這個 github issue 提到的問題…

網(wǎng)上看到渴邦,一個線程負責(zé) accept疯趟,其它線程負責(zé) epoll_wait 的主流方案是,通過 pipeeventfd 傳送 fd谋梭,在負責(zé) epoll_wait 的線程中執(zhí)行注冊信峻。(同時可以通過對多個 epoll_wait的線程進行負載均衡。)

小結(jié)

最近感覺近幾年 Linux 內(nèi)核更新得挺快的瓮床,需要的時候還是去看對應(yīng)版本的 man page 比較靠譜…

另外盹舞,學(xué)習(xí)學(xué)習(xí)就好,I/O 多路復(fù)用的事還是交給庫和框架吧 ^_^

參考文檔


(2018.07.29 更新“線程安全性”一節(jié)吼鱼。)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末蓬豁,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子菇肃,更是在濱河造成了極大的恐慌地粪,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,948評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件琐谤,死亡現(xiàn)場離奇詭異蟆技,居然都是意外死亡,警方通過查閱死者的電腦和手機斗忌,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,371評論 3 385
  • 文/潘曉璐 我一進店門质礼,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人织阳,你說我怎么就攤上這事眶蕉。” “怎么了唧躲?”我有些...
    開封第一講書人閱讀 157,490評論 0 348
  • 文/不壞的土叔 我叫張陵造挽,是天一觀的道長碱璃。 經(jīng)常有香客問我,道長饭入,這世上最難降的妖魔是什么嵌器? 我笑而不...
    開封第一講書人閱讀 56,521評論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮谐丢,結(jié)果婚禮上嘴秸,老公的妹妹穿的比我還像新娘。我一直安慰自己庇谆,他們只是感情好,可當我...
    茶點故事閱讀 65,627評論 6 386
  • 文/花漫 我一把揭開白布凭疮。 她就那樣靜靜地躺著饭耳,像睡著了一般。 火紅的嫁衣襯著肌膚如雪执解。 梳的紋絲不亂的頭發(fā)上寞肖,一...
    開封第一講書人閱讀 49,842評論 1 290
  • 那天,我揣著相機與錄音衰腌,去河邊找鬼新蟆。 笑死,一個胖子當著我的面吹牛右蕊,可吹牛的內(nèi)容都是我干的琼稻。 我是一名探鬼主播,決...
    沈念sama閱讀 38,997評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼饶囚,長吁一口氣:“原來是場噩夢啊……” “哼帕翻!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起萝风,我...
    開封第一講書人閱讀 37,741評論 0 268
  • 序言:老撾萬榮一對情侶失蹤嘀掸,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后规惰,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體睬塌,經(jīng)...
    沈念sama閱讀 44,203評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,534評論 2 327
  • 正文 我和宋清朗相戀三年歇万,在試婚紗的時候發(fā)現(xiàn)自己被綠了揩晴。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,673評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡贪磺,死狀恐怖文狱,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情缘挽,我是刑警寧澤瞄崇,帶...
    沈念sama閱讀 34,339評論 4 330
  • 正文 年R本政府宣布呻粹,位于F島的核電站,受9級特大地震影響苏研,放射性物質(zhì)發(fā)生泄漏等浊。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,955評論 3 313
  • 文/蒙蒙 一摹蘑、第九天 我趴在偏房一處隱蔽的房頂上張望筹燕。 院中可真熱鬧,春花似錦衅鹿、人聲如沸撒踪。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,770評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽制妄。三九已至,卻和暖如春泵三,著一層夾襖步出監(jiān)牢的瞬間耕捞,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,000評論 1 266
  • 我被黑心中介騙來泰國打工烫幕, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留俺抽,地道東北人。 一個月前我還...
    沈念sama閱讀 46,394評論 2 360
  • 正文 我出身青樓较曼,卻偏偏與公主長得像磷斧,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子捷犹,可洞房花燭夜當晚...
    茶點故事閱讀 43,562評論 2 349

推薦閱讀更多精彩內(nèi)容