epoll_ctl 一次註冊,epoll_wait 直接返回就緒集合。| 模式 | 特性 | 適用場景 |
|---|---|---|
| LT (Level Triggered) | 緩衝區有資料就持續通知;支援阻塞/非阻塞 | 簡單可靠、預設模式 |
| ET (Edge Triggered) | 狀態變化瞬間通知一次;必須非阻塞 | 高效能、需循環讀寫至 EAGAIN |
int epoll_create(int size); // 建立 epoll 實例 int epoll_ctl(int epfd, int op, int fd, struct epoll_event *ev); // 註冊/修改/刪除 int epoll_wait(int epfd, struct epoll_event *events, int maxevents, int timeout); // 等待事件epoll_event 關鍵欄位:
struct epoll_event {
uint32_t events; // EPOLLIN, EPOLLOUT, EPOLLET, EPOLLONESHOT...
epoll_data_t data; // 聯合體:fd / ptr / u32 / u64
};
#define MAX_EVENTS 10000
int epfd = epoll_create(MAX_EVENTS);
struct epoll_event ev, events[MAX_EVENTS];
ev.events = EPOLLIN | EPOLLET; // 讀就緒 + 邊緣觸發
ev.data.fd = listener;
epoll_ctl(epfd, EPOLL_CTL_ADD, listener, &ev);
while (1) {
int n = epoll_wait(epfd, events, MAX_EVENTS, -1);
for (int i = 0; i < n; i++) {
if (events[i].data.fd == listener) {
// 新連線
int cfd = accept(listener, ...);
fcntl(cfd, F_SETFL, O_NONBLOCK); // ET 必須非阻塞
ev.data.fd = cfd;
epoll_ctl(epfd, EPOLL_CTL_ADD, cfd, &ev);
send(cfd, welcome_msg, ...);
} else {
// 讀取客戶端資料 (循環讀至 EAGAIN)
handle_client(events[i].data.fd);
}
}
}
void handle_client(int fd) {
char buf[4096];
while (1) {
int r = read(fd, buf, sizeof(buf));
if (r > 0) broadcast(buf, r);
else if (r == 0) { close_fd(fd); break; } // 對端關閉
else if (errno == EAGAIN || errno == EWOULDBLOCK) break; // 資料讀完
else { perror("read"); close_fd(fd); break; }
}
}
10,000 客戶端並發連線,伺服端處理時間 < 1 秒,CPU 佔用極低,驗證 epoll ET 模式高併發能力。
epoll 以「事件就緒通知 + 就緒集合返回」取代 select/poll 的「輪詢全量集合」,配合 ET 模式與非阻塞 IO,成為 Linux 高併發網路伺服器的標準基石。掌握其 API、模式差異、ET 讀寫循環邏輯,是系統級網路程式設計核心能力。