Windows XP Windows 7 Windows 2003 Windows Vista Windows 綜合教學 Linux 系統教學
Windows 10 Windows 8 Windows 2008 Windows NT Windows Server 電腦軟體教學
您现在的位置: Windows教程網 >> Windows教程 >  >> Linux 系統教學 >> Linux 教學

Linux I/O 多路複用三雄對決:select vs poll vs epoll 核心機制、效能與適用場景深度比較

編輯:Linux 教學

本質相同:同步 I/O 多路複用

三者皆由應用程式將一組檔案描述符 (FD) 交給核心監控,核心在任一 FD 就緒 (可讀/可寫/異常) 時通知應用程式,應用程式再自行發起實際讀寫 (阻塞或非阻塞)。核心不負責資料搬移,故屬同步 I/O。

select (POSIX.1-2001)

int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);
  • 單進程 FD 上限 FD_SETSIZE (通常 1024),可修改重編核心但效能不升反降。
  • 每次呼叫需將三組 fd_set 從使用者空間複製到核心空間 (O(n)),返回後再複製回來並全掃描 找就緒 FD (O(n))。
  • FD 集合以位圖表示,FD_SET/FD_CLR/FD_ISSET 操作。

poll (POSIX.1-2001)

int poll(struct pollfd *fds, nfds_t nfds, int timeout);
struct pollfd { int fd; short events; short revents; };
  • 無 FD 數量硬性上限 (受限於 RLIMIT_NOFILE 與記憶體)。
  • events 輸入關注事件,revents 輸出實際事件,避免 select 的輸入輸出共用位圖問題。
  • 仍需全掃描 fds 陣列 (O(n)),大量連線時效能線性下降。

epoll (Linux 2.5.44+ 專有)

事件驅動 + 回調機制,避免全掃描,是 Linux 高併發網路編程標準選擇。

三大核心 API

// 1. 建立 epoll 實例,返回一個 FD (epfd)
int epoll_create(int size);  // size 為初始分配提示,現核心動態擴展
// 建議用 epoll_create1(EPOLL_CLOEXEC)

// 2. 註冊/修改/刪除 FD 及關注事件
int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);
op: EPOLL_CTL_ADD / EPOLL_CTL_MOD / EPOLL_CTL_DEL
struct epoll_event {
    uint32_t events;   // EPOLLIN, EPOLLOUT, EPOLLET, EPOLLONESHOT...
    epoll_data_t data; // 用戶自訂資料 (ptr/fd/u32/u64)
};

// 3. 等待就緒事件
int epoll_wait(int epfd, struct epoll_event *events, int maxevents, int timeout);
// 返回就緒事件數量,events 陣列填入就緒事件資訊
// timeout: -1 永久阻塞, 0 非阻塞輪詢, >0 毫秒超時

關鍵事件旗標

  • EPOLLIN:可讀 (含對端正常關閉 FIN)
  • EPOLLOUT:可寫
  • EPOLLET:邊緣觸發 (Edge Triggered) — 僅在狀態變化瞬間通知一次,需配合非阻塞 IO 循環讀寫至 EAGAIN,適合高併發。
  • EPOLLONESHOT:一次性通知,處理完需再次 epoll_ctl MOD 重新啟用,常用於執行緒池分發任務避免驚群。

水平觸發 (LT, 預設) vs 邊緣觸發 (ET)

模式通知時機編程複雜度適用場景
LT (水平觸發)FD 就緒狀態持續期間反覆通知低,類似 select/poll一般應用、快速原型
ET (邊緣觸發)FD 從未就緒→就緒的瞬間通知一次高,必須非阻塞 + 循環讀寫高併發、長連線 (Nginx, Redis, Netty)

效能對比總結

指標selectpollepoll
FD 數量上限1024 (預設)無硬性上限無硬性上限 (受限於系統 max open files)
時間複雜度O(n) 全掃描O(n) 全掃描O(1) 就緒事件回調
核心/用戶空間複製每次三組位圖雙向複製每次陣列雙向複製僅就緒事件複製 (透過共享記憶體 epoll_event)
大量閒置連線極差極差優異 (僅活躍連線觸發回調)
可移植性跨平台 (POSIX)跨平台 (POSIX)Linux 專有

選型建議

  • 連線數 < 1000、需跨平台:select/poll 簡單足夠。
  • 高併發 (萬級+)、長連線、Linux 專用:epoll (LT 起步,效能瓶頸再改 ET)。
  • 避坑指南:epoll 必須對 FD 設 O_NONBLOCK;ET 模式必須循環 read/write 至 EAGAIN;定期檢查 epoll_wait 返回值處理錯誤/關閉;使用 EPOLLONESHOT 配合執行緒池避免同一連線並發處理。
Copyright © Windows教程網 All Rights Reserved