21. socket中的多路复用,及其优缺点,epoll的水平和边缘触发模式?

多路复用是一种单线程/进程管理多个Socket连接的技术,核心是通过系统调用监听多个文件描述符(FD),当某个FD就绪(可读/可写/异常)时通知程序处理,避免阻塞等待。常见的实现方式有:

  1. select
  2. poll
  3. epoll(Linux特有,高性能)

1. select/poll/epoll对比

特性selectpollepoll
时间复杂度O(n)O(n)O(1)
FD数量限制1024(默认)无限制无限制
工作模式轮询轮询回调(事件驱动)
内核态/用户态拷贝每次需拷贝全部FD集合同select仅传递就绪的FD(mmap优化)
适用场景跨平台、少量连接少量连接高并发(如10万+连接)

2. epoll的核心优势

epoll是Linux下高性能多路复用的实现,解决了select/poll的缺陷:

  • 无需线性扫描FD:通过红黑树管理FD,就绪时直接回调通知。
  • 无FD数量限制:仅受系统最大文件描述符数限制。
  • 边缘触发(ET)模式:减少事件重复触发的开销。

epoll的关键函数

int epoll_create(int size);  // 创建epoll实例
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);  // 等待事件

3. epoll的触发模式

(1) 水平触发(LT,Level-Triggered)

  • 默认模式,只要FD处于就绪状态(如缓冲区有数据),就会持续触发事件。
  • 特点
    • 类似select/poll的行为。
    • 如果未一次性读完数据,下次epoll_wait会再次通知。
  • 优点:编程简单,不易遗漏事件。
  • 缺点:可能引发多次无意义的唤醒(如数据未读完时)。
LT示例代码
struct epoll_event event;
event.events = EPOLLIN | EPOLLLT;  // 水平触发(默认)
epoll_ctl(epfd, EPOLL_CTL_ADD, sockfd, &event);

(2) 边缘触发(ET,Edge-Triggered)

  • 仅在FD状态变化时触发一次(如从不可读变为可读)。
  • 特点
    • 必须非阻塞IO + 循环读写直到EAGAIN,否则会丢失后续数据。
    • 高性能,减少重复事件。
  • 优点:减少无效唤醒,适合高并发。
  • 缺点:编程复杂,需处理不全读/写的情况。
ET示例代码
struct epoll_event event;
event.events = EPOLLIN | EPOLLET;  // 边缘触发
epoll_ctl(epfd, EPOLL_CTL_ADD, sockfd, &event);

// 必须非阻塞读取!
while (read(fd, buf, sizeof(buf)) > 0);  // 读到EAGAIN为止

4. 多路复用的优缺点

优点

  1. 高并发:单线程可管理数万连接(相比多线程/进程更节省资源)。
  2. 避免阻塞:无需为每个连接创建独立线程。
  3. 精准事件通知(epoll):仅处理就绪的FD。

缺点

  1. 编程复杂(尤其是ET模式需非阻塞IO + 循环读写)。
  2. 仅适用于IO密集型场景:CPU密集型任务仍需多线程。
  3. 平台依赖性(如epoll仅限Linux)。

5. 面试常见问题

Q1: 为什么epoll比select/poll高效?

  • select/poll需轮询所有FD,而epoll仅回调就绪的FD
  • select/poll每次调用需全量拷贝FD集合,epoll通过mmap共享内存减少拷贝。

Q2: ET模式下为什么要用非阻塞IO?

  • ET模式只通知一次,如果阻塞读取且未读完,后续数据到达时不会再次触发,导致数据滞留。

Q3: LT和ET如何选择?

  • LT:适合简单场景(如HTTP服务器)。
  • ET:适合高性能场景(如Redis、Nginx),但需确保正确处理读写。

总结

要点说明
多路复用核心单线程管理多个Socket,避免阻塞等待。
epoll优势事件驱动、O(1)复杂度、无FD限制。
LT vs ETLT持续触发,ET仅状态变化时触发(需非阻塞IO)。
适用场景高并发网络编程(如Web服务器、即时通讯)。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

芒果敲代码

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值