首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

Linux epoll 事件類型完整解析:EPOLLIN/OUT/PRI/RDHUP/ERR/HUP 觸發條件與邊緣觸發實戰

     編輯:關於C語言

epoll 核心事件類型

事件宏觸發條件說明
EPOLLIN可讀:新連線到達、資料到達、對端正常關閉最常用,包含聽套接字接受連線
EPOLLOUT可寫:發送緩衝區有空間通常只在需要寫入時註冊,寫完即移除
EPOLLPRI帶外資料(Urgent data,TCP OOB)極少用,需 SO_OOBINLINE 配合
EPOLLRDHUP對端關閉連線或半關閉(關閉寫端)Linux 2.6.17+,檢測對端正常關閉的最佳方式
EPOLLERR套接體發生錯誤(本端錯誤)不需註冊,epoll_wait 永遠回報
EPOLLHUP套接體掛起(本端異常)不需註冊,epoll_wait 永遠回報

關鍵觸發場景實測

1. 聽套接字

  • 註冊:EPOLLIN(或 EPOLLET | EPOLLIN)。
  • 新連線到達 → 觸發 EPOLLIN。

2. 客戶端正常關閉 close()/kill/Ctrl+C

  • 伺服端收到:**EPOLLIN + EPOLLRDHUP**。
  • 不觸發 EPOLLERR/EPOLLHUP(這兩者為本端錯誤)。
  • 處理:recv() 回傳 0 → epoll_ctl(DEL) → close()。
  • 若系統不支援 EPOLLRDHUP:僅依賴 EPOLLIN + recv()==0 判斷。

3. 客戶端異常斷開(拔網線、進程崩潰、防火牆截斷)

  • 無任何事件自動觸發(TCP 無心跳機制)。
  • 必須**主動探測**:
    1. 應用層心跳(定時發送 Ping)。
    2. SO_KEEPALIVE(系統級,預設 2 小時,可調整)。
    3. 嘗試 write()/send() → 觸發 EPOLLERR(發現對端已斷)。

4. 帶外資料

  • 僅觸發 EPOLLPRI,不觸發 EPOLLIN。

EPOLLERR/EPOLLHUP 深度釐清

這兩個事件表示「本端(伺服器)發生錯誤/掛起」,而非對端斷開。只有當伺服器對已關閉的套接體進行 read/write 時,才會在該套接體上觸發 EPOLLERR,進而得知對端已不可用。

因此:不能依賴 EPOLLERR/EPOLLHUP 被動檢測對端異常斷開,必須結合心跳或定時探測。

邊緣觸發 (ET) vs 水平觸發 (LT)

模式觸發條件程式設計要求
LT (預設)狀態滿足即持續觸發(如緩衝區有資料)簡單,可反覆處理
ET狀態**變化**時觸發一次(資料從無到有)**必須非阻塞 + 一次讀寫盡可能多** (loop until EAGAIN),否則資料遺漏

EPOLLET 與事件類型組合:EPOLLET | EPOLLIN。

EPOLLONESHOT (Linux 2.6.2+)

事件觸發一次後**自動從 epoll 移除**,需手動 epoll_ctl(MOD) 重新註冊。用於**執行緒池分發任務**,確保同一連線同一時間僅由一執行緒處理。

實戰建議清單

  1. 聽套接字:EPOLLIN (LT) 即可。
  2. 連線套接字:EPOLLIN | EPOLLRDHUP (LT) 或 EPOLLET | EPOLLIN | EPOLLRDHUP (ET)。
  3. 需寫入時動態加 EPOLLOUT,寫完移除。
  4. 異常斷開檢測:**應用層心跳 + SO_KEEPALIVE** 雙重保險。
  5. EPOLLERR/EPOLLHUP 視為本端嚴重錯誤,直接關閉清理。
  6. ET 模式下 recv/send 必須循環至 EAGAIN/EWOULDBLOCK。

總結

epoll 事件機制核心在於區分「對端正常關閉」(EPOLLRDHUP)與「本端錯誤」(EPOLLERR/HUP),**異常斷開無法被動檢測**是網路程式設計的鐵律。正確使用 EPOLLRDHUP、心跳機制、ET 模式非阻塞循環讀寫,構建高效穩健的高併發網路伺服器。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved