一、IO多路复用
二、多路复用的实现方式
select函数
int select(int nfds, fd_set *readfds, fd_set *writefds,fd_set *exceptfds, struct timeval *timeout);
poll函数
int poll(struct pollfd *fds, nfds_t nfds, int timeout);
epoll 函数族
epoll_create
epoll_wait
epoll_ctl
三、poll函数
poll函数 :事件类型
events:
POLLIN:有数据可读
POLLPRI:有紧急数据需要读取
POLLOUT: 文件可写
.....
四、epoll函数族
1./*创建epoll句柄*/
int epoll_create(int size); //size参数实际上已经被弃用
2./*epoll句柄的控制接口*/
int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);
epfd: epoll 专用的文件描述符,epoll_create()的返回值
op: 表示动作,用三个宏来表示:
EPOLL_CTL_ADD:注册新的 fd 到 epfd 中;
EPOLL_CTL_MOD:修改已经注册的fd的监听事件;
EPOLL_CTL_DEL:从 epfd 中删除一个 fd;
fd: 需要监听的文件描述符
event: 告诉内核要监听什么事件
epoll_event结构体
typedef union epoll_data {
void *ptr;
int fd;
__uint32_t u32;
__uint64_t u64;
} epoll_data_t;
struct epoll_event {
__uint32_t events; /* Epoll events */
epoll_data_t data; /* User data variable */
};
EPOLLIN :表示对应的文件描述符可以读(包括对端 SOCKET 正常关闭);
EPOLLOUT:表示对应的文件描述符可以写;
EPOLLPRI:表示对应的文件描述符有紧急的数据可读(这里应该表示有带外数据到来);
EPOLLERR:表示对应的文件描述符发生错误;
EPOLLHUP:表示对应的文件描述符被挂断;
EPOLLET :将 EPOLL 设为边缘触发(Edge Trigger)模式,这是相对于水平触发(Level Trigger)来说的。
EPOLLONESHOT:只监听一次事件,当监听完这次事件之后,如果还需要继续监听这个 socket 的话,需要再次把这个 socket 加入到 EPOLL 队列里
3./*等待 epoll 文件描述符上的 I/O 事件*/
int epoll_wait(int epfd, struct epoll_event *events, int maxevents, int timeout);
epfd: epoll 专用的文件描述符,epoll_create()的返回值
events: 分配好的 epoll_event 结构体数组,epoll_wait 将会把发生的事件赋值到events 数组中
maxevents: events 数组的元素个数
timeout: 超时时间,单位为毫秒,为 -1 时,函数为阻塞