select
poll
int poll(struct pollfd *fds, nfds_t nfds, int timeout);
- fds:监听的文件描述符
- nfds:监听数组的,实际有效监听个数
- timeout: > 0超时时长,单位(毫秒)。-1阻塞等待,0不阻塞
struct pollfd{
int fd; //待监听的文件描述符
short events; //待监听的文件描述符对应的监听事件,取值POLLIN、POLLOUT、POLLERR
short revnets; // 传入时,给0.如果满足对应事件的话,返回非0->POLLIN、POLLOUT、POLLERR
}
优点:自带数组结构,可以将监听事件集合和返回事件集合分离。拓展监听上限。超出1024限制
缺点:不能跨平台。无法直接定位满足监听事件的文件描述符,编码难度较大
突破1024文件描述符限制
cat /proc/sys/fs/file-max // 当前计算机所能打开的最大文件个数。受硬件影响
ulimit -a // 当前用户的进程下,默认打开文件描述符个数(open files)。缺省为1024
修改:
sudo vim /etc/security/limits.conf
写入
soft nofile 65536 //设置默认值,可以直接借助命令修改。注销用户使其生效
hard nofile 100000 // 命令修改上限
epoll
int epoll_create(int size); //创建一棵监听红黑树
- size:创建新的红黑树的监听节点数量(仅供内核参考)
- 返回值:指向新创建的红黑树的根节点的fd。失败,-1 errno
int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event); //操作监听红黑树
- epfd:epoll_create函数的返回值
- op:对该监听红黑树所做的操作(EPOLL_CTL_ADD添加fd到监听红黑树、EPOLL_CTL_MOD修改fd在监听红黑树上的监听事件、EPOLL_CTL_DEL将一个fd从监听红黑树上摘下(取消监听))
- fd:待监听的fd。本质是struct epoll_event
- events:EPOLLIN、EPOLLOUT、EPOLLERR
int epoll_wait(int epfd, struct epoll_event *events, int maxevents, int timeout);
- epfd:epoll_create函数的返回值
- events:传输参数[数组],满足监听条件的哪些fd的结构体
- maxevents:数组元素的总个数。 1024
- timeout:-1阻塞。0不阻塞。>0超时(毫秒)
- epoll事件模型
- ET模式:
边沿触发:缓冲区剩余未读尽的数据不会导致epoll_wait返回。新的事件满足,才会触发。
struct epoll_event event;
event.events = EPOLLIN | EPOLLET;
- LT模式:
水平触发(默认):缓冲区剩余未读尽的数据会导致epoll_wait返回
-
结论:
epoll的ET模式,高效模式,但是只支持非阻塞模式。——忙轮询
优点:突破1024文件描述符
缺点:不能跨平台 -
epoll反应堆模型:
-
epoll ET模式 + 非阻塞、轮询 + void *ptr
-
原来: socket、bind、listen – epoll_create 创建监听 红黑树 – 返回 epfd – epoll_ctl() 向树上添加一个监听fd – while(1)-- epoll_wait 监听 – 对应监听fd有事件产生 – 返回 监听满足数组 – 判断返回数组元素 – lfd满足 – Accept – cfd 满足 – read() — 小->大 – write回去。
-
反应堆:不但要监听 cfd 的读事件、还要监听cfd的写事件。
socket、bind、listen – epoll_create创建监听红黑树 – 返回epfd – epoll_ctl()向树上添加一个监听fd – while(1)-- epoll_wait监听 – 对应监听fd有事件产生 – 返回监听满足数组 – 判断返回数组元素 – lfd满足 – Accept – cfd满足 – read() — 小->大 – cfd从监听红黑树上摘下 – EPOLLOUT – 回调函数 – epoll_ctl() – EPOLL_CTL_ADD 重新放到红黑上监听写事件 – 等待 epoll_wait 返回 – 说明 cfd 可写 – write回去 – cfd从监听红黑树上摘下 – EPOLLIN – epoll_ctl() – EPOLL_CTL_ADD 重新放到红黑上监听读事件 – epoll_wait 监听 -
eventset函数:设置回调函数。 lfd --》 acceptconn(); cfd --> recvdata(); cfd --> senddata();
-
eventadd函数:将一个fd,添加到监听红黑树。 设置监听read事件,还是监听写事件。