【网络】多路IO复用
多路I/O复用
-
多路I/O复用:
- 多路I/O复用就是用一个线程或者进程同时监听多个文件描述符(套接字、管道等)的I/O事件(如可读、可写、异常)的技术;通过多路I/O复用,程序可以在不阻塞情况下同时处理多个连接请求,显著提升网络服务器的并发处理能力
-
多路I/O复用的优点:
- 支持高并发:单个线程可以同时处理(监听)多个I/O操作
- 资源高效、减少线程切换开销:减少线程的创建和切换,节约系统资源
- 简化程序结构:多路IO复用不需要处理复杂的线程管理以及同步问题
-
常见的多路I/O复用技术:
-
select:(优点:简单,易用,跨平台;缺点:受最大FD限制,每次调用须全量拷贝文件描述符到内核空间)
select
函数会监视多个文件描述符的集合,当其中任何一个文件描述符上的 I/O 事件(可读、可写、异常)发生时,select
函数会返回,通过遍历文件描述符集合来确定哪些文件描述符发生了事件
-
poll:(优点:不受FD限制;缺点:每次调用须全量拷贝文件描述符至内核空间,遍历整个
pollfd
数组来确定哪些文件描述符发生了事件)poll
是监视多个文件描述符的集合,使用一个pollfd
结构体数组来表示要监视的文件描述符,没有最大文件描述符数量的限制
-
epoll:(优点:高效、支持大规模连接;缺点:使用红黑树+链表,内存消耗高且仅适用Linux系统)
-
epoll
是 Linux 特有的 I/O 复用机制,它使用事件驱动的方式,通过epoll_ctl
函数注册文件描述符和对应的事件,当事件发生时,epoll_wait
函数会返回发生事件的文件描述符列表,避免了遍历所有文件描述符的开销。
-
epoll工作流程:
-
创建epoll实例:
int epoll_fd = epoll_create1(0);
-
注册监控事件:
struct epoll_event event; event.events = EPOLLIN; // 监控可读事件 event.data.fd = sockfd; epoll_ctl(epoll_fd, EPOLL_CTL_ADD, sockfd, &event);
-
等待事件就绪:
int num_ready = epoll_wait(epoll_fd, events, MAX_EVENTS, -1);
-
处理就绪事件:
-
-
-
-
水平触发(LT):
- 默认情况下,epoll提供水平触发;只要文件描述符处于就绪态(如可读、可写等),就会一直通知应用程序。应用程序可以在任何时间检查文件描述符的状态,并进行相应的I/O操作
- 适用于文件描述符少场景:如果文件描述符就绪,应用程序没有处理完所有数据,系统就会持续通知
-
边缘触发(EL):
- 只有在文件描述符发生变化时(例如从不可读变为可读),才会通知应用程序。应用程序需要一次处理所有就绪的数据,否则可能会丢失事件。
- 适合高并发场景:只在状态变化时通知一次,减少事件通知次数,适合高并发场景。