【网络工程】epoll 深度剖析:ET/LT 模式、源码分析与性能特征
epoll 是 Linux 高性能网络编程的基石。本文深入剖析 epoll 的内核数据结构(红黑树与就绪链表)、ET 和 LT 两种触发模式的行为差异与编程范式、惊群问题及 EPOLLEXCLUSIVE 的解决方案。
发布来自土法炼钢兴趣小组的知识、笔记、进展和应用。主题包括数据结构和算法、编程语言、网络安全、密码学等。
共 22 篇文章 · 返回首页
epoll 是 Linux 高性能网络编程的基石。本文深入剖析 epoll 的内核数据结构(红黑树与就绪链表)、ET 和 LT 两种触发模式的行为差异与编程范式、惊群问题及 EPOLLEXCLUSIVE 的解决方案。
数据从磁盘到网卡的传统路径涉及 4 次拷贝和多次上下文切换。本文系统剖析 sendfile、splice、vmsplice、MSG_ZEROCOPY 四种零拷贝技术的内核实现、适用场景与性能差异,并以 Kafka 和 Nginx 为案例分析零拷贝在生产系统中的工程实践。
你调用 kmalloc(64, GFP_KERNEL),内核在 3 微秒内给了你 64 字节。背后是两层精密的机械:伙伴系统管理物理页面,SLUB 把页面切碎成小对象。这两层如何配合?各自解决了什么问题?
你的 ext4 文件系统上有一个 1TB 的数据库文件。内核如何在 O(log n) 时间内找到文件偏移量 847,293,510,144 对应的物理磁盘块?答案藏在 extent tree 里。本文逐一拆解 ext4、XFS、btrfs、ZFS、F2FS 五种文件系统的树形结构设计。
Linux 内核如何在并发数据结构中实现读侧零开销?RCU 用一种违反直觉的方式回答了这个问题:让读者永远不等待,让写者承担一切代价。
AVL 树的平衡更严格、查找更快,为什么 Linux 内核、Java TreeMap、C++ std::map 全都选了红黑树?这个问题的答案不在教科书里——它藏在旋转次数的精确分析和 cache line 的物理约束中。
你把 nice 值设成了 -20,然后发现延迟反而更高了。你用 cgroup 限了 CPU,然后发现交互式 shell 卡成幻灯片。调度器不是'谁优先级高谁先跑'这么简单——它是操作系统中最复杂的博弈论。
你把数据库从 HDD 迁移到了 NVMe SSD,IOPS 涨了 100 倍——然后你发现 I/O 调度器还在用 CFQ,它正在用复杂的算法把你的 NVMe 搞慢。NVMe 时代,最好的调度器可能是'不调度'。
Nginx 用一个进程处理 10 万个并发连接,核心就是 epoll。但 epoll 的 O(1) 性能不是魔法——它用红黑树存储监控集合,用链表收集就绪事件,用回调避免轮询。三个数据结构各司其职,精妙得像一台钟表。
一台繁忙的 Nginx 服务器上有 100 万个活跃连接,每个连接都有 keepalive 超时定时器。如果用最小堆管理这些定时器,每次新连接到来都要 O(log n) 插入——100 万个定时器意味着 20 次比较。时间轮用 O(1) 解决了这个问题。
容器不是魔法。它就是几个系统调用。本文用 C 从 clone() 开始,逐个开启 PID/UTS/Mount/IPC namespace,看隔离到底是怎么回事。50 行代码,你就拥有了一个'容器'的雏形。
上一篇我们用 clone() 隔离了 PID、主机名和挂载点,但那个'容器'连 lo 都 ping 不通。本文从 CLONE_NEWNET 出发,用 veth pair + bridge + iptables MASQUERADE,一步步给容器接上网。
chroot 不是安全边界——10 行 C 就能逃出去。本文用 pivot_root 构建真正隔离的容器根文件系统:从 Alpine minirootfs 到设备节点,从 mount propagation 到只读根,一步步把容器的'地基'打牢。
你给容器设了 512MB 内存限制,结果宿主机上的数据库被 OOM-kill 了。Cgroups 不是'加个限制'那么简单 — v1 的设计是个历史错误,v2 才是正确答案。本文用 C 代码从 mkdir 开始,手动创建 cgroup,设 CPU/内存/IO 限制,压测,看它怎么把进程关进笼子。
你的容器能调用 reboot()。是的,现在就能。除非有人拦住它。Capabilities 拆分 root 权限,Seccomp-BPF 过滤系统调用——两道防线,缺一不可。本文用 C 代码拆解这两套机制,看看 Docker 到底替你挡住了什么。
从 NIC 驱动到用户态 read(),一个网络包在 Linux 内核中到底经历了什么?本文拆解 sk_buff、NAPI、softirq、netfilter 的完整收包路径,并用 bpftrace 实测追踪每一跳的延迟。
Netfilter 五个 hook 点、四表五链的真实遍历顺序、conntrack 状态机与性能开销、SNAT/DNAT/MASQUERADE 辨析,再到 nftables 替代方案和 eBPF 数据面——从内核视角拆解 Linux 防火墙。
eBPF 让你在内核里插代码而不用写内核模块。听起来很美,但验证器的限制、Map 的性能陷阱、BTF 的兼容性噩梦,这些他们不会在教程里告诉你。
Seccomp 只能说 yes or no,但攻击者早就学会了在 yes 里面做文章。是时候让 eBPF 接管安全审计了。
当 DDoS 洪水来袭,iptables 在协议栈里挣扎,而 XDP 在网卡驱动层就把垃圾包丢了。不进协议栈、不分配 skb、不走 netfilter——这才是丢包该有的样子。
io_uring 一定比 epoll 快?跑五个场景的实测数据告诉你:某些情况下 epoll 还是赢的。用数据打自己的脸。
SQPOLL 烧 CPU、fixed buffer 内存泄漏、CQE overflow 丢事件、内核版本兼容性噩梦——io_uring 在生产中踩过的坑,逐个拆解。