libuv 是 Node.js 的底層跨平台異步 I/O 庫,封裝了 Windows IOCP、Linux epoll、macOS kqueue 等。掌握它能深入理解現代高併發網絡模型。但 libuv 封裝層較厚,源碼閱讀門檻高。建議學習路徑:
README.md 編譯安裝(遇問題上 Stack Overflow)。int epoll_create(int size); // 創建 epoll 實例,返回 fd
int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event); // 註冊/修改/刪除 fd
int epoll_wait(int epfd, struct epoll_event *events, int maxevents, int timeout); // 等待就緒事件
// 事件結構
struct epoll_event {
uint32_t events; // EPOLLIN, EPOLLOUT, EPOLLET, EPOLLONESHOT...
epoll_data_t data; // 聯合體:fd / ptr / u32 / u64
};
#include <stdio.h>
#include <sys/epoll.h>
#include <unistd.h>
#define MAX_BUF 255
int main() {
int epfd = epoll_create(1);
struct epoll_event ev = { .events = EPOLLIN, .data.fd = STDIN_FILENO };
epoll_ctl(epfd, EPOLL_CTL_ADD, STDIN_FILENO, &ev);
for (;;) {
struct epoll_event evs[1];
int nfds = epoll_wait(epfd, evs, 1, -1);
if (nfds > 0 && evs[0].data.fd == STDIN_FILENO) {
char buf[MAX_BUF];
int len = read(STDIN_FILENO, buf, MAX_BUF-1);
buf[len] = '\0';
printf("Input: %s", buf);
}
if (random() % 100 >= 90) break; // 隨機退出演示
}
close(epfd);
return 0;
}
關鍵點:
EPOLLET 邊緣觸發:必須配合非阻塞 fd,一次性讀寫完緩衝區。epoll_wait 分發新連接,pthread_create 處理業務(讀取請求、寫回響應)。read/write。// 編譯:gcc -g -Wall -o epoll_srv epoll_srv.c -lpthread
// 完整代碼見原文,核心流程:
// 1. socket/bind/listen + 設置非阻塞 + SO_REUSEADDR
// 2. epoll_create + EPOLL_CTL_ADD 監聽 fd (EPOLLIN|EPOLLET)
// 3. 循環 epoll_wait:
// - 新連接:accept → 設置非阻塞 → EPOLL_CTL_ADD 客戶端 fd
// - 可讀事件:pthread_create 處理請求/響應
// 4. 工作線程:read 循環 → write 響應 → close fd → pthread_exit
set fenc=utf-8 | set fencs=utf-8,gbk,gb2312
set nocompatible | set number | set autoindent | set smartindent
set tabstop=4 | set shiftwidth=4 | set ruler | set incsearch
set ignorecase | set showmatch | syntax on
網絡開發沒有銀彈。libuv 適合快速落地產品;epoll 適合深入內核機制、打造自研高性能框架。建議:先用 libuv 交付,再啃 epoll 源碼內功。