Linux I/O Multiplexing
程序需要处理多路I/O,有以下几种方案:
1. 阻塞I/O
单个线程无法在多个文件描述符上阻塞,故每个线程仅能处理一路I/O,这是个比较奢侈的方案,仅使用在少部分场景中。
2. 非阻塞I/O
非阻塞I/O在遇到I/O没有准备好的情况时会立即返回,给单个线程处理多路I/O提供了可能。但是这种方式也存在一个弊端:线程必须使用轮询的方式向自己管理的多路I/O发送请求,轮询并不是一个高效的CPU使用方式。
3. 异步I/O
4. I/O Multiplexing
I/O Multiplexing技术支持程序在多路I/O上阻塞,并且在其中某路I/O准备好时收到通知。
I/O Multiplexing的实现主要由三个:select(), poll(), epoll(), pselect()和ppoll()是select()和poll()的改进版本,主要增加了信号掩码的支持。
在使用I/O Multiplexing时,需要首先构建出我们感兴趣的I/O集合,然后调用一个函数,直到这些I/O中的一个已经准备完成该,该函数才返回。
4.1 select()
#include <sys/select.h>
int select(int nfds, fd_set* readfds, fd_set* writefds, fd_set* exceptfds, struct timeval* timeout);
int pselect(int nfds, fd_set* readfds, fd_set* writefds, fd_set* exceptfds,
const struct timespec* timeout, const sigset_t* sigmask);
其中,readfds, writefds和exceptfds分别代表监控的读、写和异常文件描述符的集合,timeout表示等待时间。
4.2 poll()
#include <poll.h>
int poll(struct pollfd* fd, nfds_t nfds, int timeout);
struct pollfd {
int fd;
short events;
short revents;
};
4.3 Event Poll
#include <sys/epoll.h>
int epoll_create1(int flags);
int epoll_ctl(int epfd, int op, int fd, struct epoll_event* event);
int epoll_wait(int epfd, struct epoll_event* events, int maxevents, int timeout);