select I/O复用技术慢的原因
调用select针对所有文件描述符的循环语句
每次调用select函数都需要像函数传递监视对象的信息
epoll
无需编写针对所有文件描述符的循环语句
无需每次传入对象信息
epoll_create
int epfd=epoll_create(1024);
传入epoll的size,书上说Linux内核会忽略size而根据情况调整大小,故参数不必在意
成功时会返回epoll的文件描述符
epoll_ctl
epoll_ctl(epfd,EPOLL_CTL_ADD,fd,__event);
该函数第一个参数是epoll的文件描述符,第二个是添加、删除等各种操作、第三个是要操作的文件描述符、第四个是监听fd对应的事件。
其中,第二个参数有 EPOLL_CTL_ADD;将描述符注册到epoll
EPOLL_CTL_DEL;将描述符删除
EPOLL_CTL_MOD:更改该描述符发生的事件
第四个参数是一个结构体
struct epoll_event event;
event.events=EPOLLIN;
event.data.fd=fd;
一般这样初始化。打他中含有其他成员,在epoll反应堆会用到
epoll_wait
int events_num=epoll_wait(epfd,events,maxevents,timeout);
该函数返回事件发生的个数,第二个参数需要动态分配,是一个events数组。第三个参数是第二个参数可以保存的最大事件个数,第四个参数是超时时间,-1为永不超时,以毫秒为单位。
条件触发和边缘触发
条件触发过程中,只要缓冲有数据就会一直通知该事件,epoll默认为条件触发。
边沿触发需要我们在添加events时,添加下列语句,并且要改套接字特性为非阻塞io。
event.events=EPOLLIN|EPOLLET;
int flag=fcntl(fd,F_GETFL,0);
fcntl(fd,F_SETFL,flag|O_NONBLOCK);
上述代码为设置非阻塞io。
边沿触发可以分离接收数据和处理数据的时间点。
边缘触发更可能带来更高性能(不绝对)。