在高併發網絡服務開發中,epoll 的邊緣觸發(ET)模式能顯著減少系統調用開銷。不同於水平觸發(LT)會持續通知就緒狀態,ET 僅在狀態發生變化時觸發一次。這要求開發者在 epoll_wait 返回後,必須循環讀寫直到該文件描述符的緩衝區耗盡(讀返回 EAGAIN 或字節數小於請求值)或寫滿為止。
本範例實現一個 Echo 服務器:收到客戶端數據後,將內容重複 REPEAT_NUM (20000) 次組裝成巨大回應包(約 400KB),專門驗證 EPOLLOUT 事件處理邏輯。關鍵點包括:
O_NONBLOCK)EPOLLIN | EPOLLETEPOLLIN | EPOLLOUT | EPOLLET,避免後續 epoll_ctl 修改事件開銷g_out_buf 記錄待發送數據、偏移量與長度,配合 g_has_write_buf 標誌實現分片發送// 發送邏輯:嘗試寫入剩餘數據,遇到 EAGAIN 則保留狀態等待下一次 EPOLLOUT
int write_out_buf(int fd, char *out_buf, int buf_len, int offset) {
int snd_len = write(fd, out_buf + offset, buf_len - offset);
// ... 循環處理短寫與 EAGAIN ...
return snd_len;
}
// EPOLLOUT 事件處理
else if (evs[i].events & EPOLLOUT) {
clientFd = evs[i].data.fd;
if (g_has_write_buf) {
g_out_buf_offset += write_out_buf(clientFd, g_out_buf, g_out_buf_len, g_out_buf_offset);
if (g_out_buf_offset == g_out_buf_len) g_has_write_buf = 0;
}
}
配套 Perl 客戶端發送 10 字節測試數據,服務器端日誌清晰展示:
epollin 讀取 10 字節 → 觸發 process_write 組裝 408890 字節回應write 僅發送 65536 字節(Socket 發送緩衝區滿)→ 觸發 EAGAINepollout 事件分片發送剩餘數據,最終完成 408890 字節全量發送此範例完整呈現 ET 模式下「讀寫循環 + 狀態機式分片發送」的標準範式,適合作為高性能網絡庫的基礎參考。代碼在 Linux 環境編譯運行,歡迎實測調優。