select/poll là O(n) scan không scale; epoll (Linux) và kqueue (BSD) dùng kernel-managed event notification, O(1) per event, scale đến hàng triệu FDs; io_uring là next-gen zero-copy async I/O.
select (POSIX): monitor tối đa 1024 FDs (FD_SETSIZE), truyền full set mỗi syscall (O(n) scan), không biết FD nào ready phải scan toàn bộ, không scale. poll: tương tự select nhưng không giới hạn 1024 FDs (dùng dynamic array), vẫn O(n) scan. epoll (Linux 2.6+): kernel-side interest list — epoll_create, epoll_ctl(ADD/MOD/DEL), epoll_wait chỉ trả về ready FDs (O(1) per event). Edge-triggered (ET) mode: notify chỉ khi state change → must drain toàn bộ; Level-triggered (LT, default): notify khi FD vẫn readable/writable → simpler. kqueue (FreeBSD/macOS): tổng quát hơn epoll — kevent struct monitor FDs, signals, timers, processes, sockets; kevent() syscall combine register và wait. Không phải chỉ network — có thể monitor file changes (không cần inotify riêng). io_uring (Linux 5.1+): next-gen async I/O — submission queue + completion queue, zero-copy, batch syscalls, giảm context switch drastically. Đang được adopt bởi Rust tokio, Node.js 18+.