【Linux】IO多路复用——select,poll,epoll的概念和使用,三种模型的特点和优缺点,epoll的工作模式
IO多路复用是指通过一种机制,程序可以同时监视多个文件描述符,一旦某个文件描述符就绪(一般是读或写就绪),就能进行相应的读写操作。在Linux中,IO多路复用通常使用select
, poll
, 和 epoll
系统调用实现。
select
:select
系统调用允许进程指定一个或多个等待的文件描述符集合,然后阻塞直到其中一个或多个文件描述符变为就绪。select
的缺点是每次调用都需要重新设置文件描述符集合,并且文件描述符数量有限制。poll
:poll
系统调用类似于select
,但没有描述符的限制。epoll
:epoll
是Linux下的一种高性能IO多路复用机制,相对于select
和poll
,epoll
使用了更加高效的事件通知机制,能够同时支持水平触发和边缘触发,并且没有文件描述符限制。
三者的特点和优缺点如下:
select
:优点:基本上在所有现代Unix/Linux系统中都有实现。
缺点:文件描述符集合需要在每次调用前重新设置,并且最大文件描述符数有限制。
poll
:优点:没有文件描述符数量的限制。
缺点:性能不如
epoll
。epoll
:优点:高效的事件通知机制,支持水平触发和边缘触发,没有文件描述符数量限制。
缺点:只在Linux 2.6及更高版本的内核中可用。
代码示例:
// 使用select
fd_set rfds;
struct timeval tv;
int retval;
// 初始化文件描述符集合
FD_ZERO(&rfds);
FD_SET(0, &rfds); // 监视标准输入
// 设置超时时间
tv.tv_sec = 1;
tv.tv_usec = 0;
// 调用select
retval = select(1, &rfds, NULL, NULL, &tv);
if (retval > 0) {
// 标准输入可读
if (FD_ISSET(0, &rfds)) {
// 读取数据
}
}
// 使用epoll
#include <sys/epoll.h>
int epfd;
struct epoll_event event;
epfd = epoll_create(10); // 创建epoll实例
event.data.fd = STDIN_FILENO; // 添加要监视的文件描述符
event.events = EPOLLIN; // 设置监视的事件类型
epoll_ctl(epfd, EPOLL_CTL_ADD, STDIN_FILENO, &event);
// 等待事件
struct epoll_event events[10]; // 事件缓冲区
int nfds = epoll_wait(epfd, events, 10, 1000); // 等待1000毫秒
for (int n = 0; n < nfds; ++n) {
if (events[n].data.fd == STDIN_FILENO) {
// 标准输入可读
// 读取数据
}
}
在实际应用中,epoll
是性能最优的选择,尤其是在处理大量并发连接时。而select
和poll
主要在向后兼容或者在不支持epoll
的旧
评论已关闭