⾯经C++ select poll epoll

select poll epoll 三者的区别

1.select poll epoll的区别
select函数原型 int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);
第一个参数是maxfd+1最大的文件描述符+1,也就是内核返回的FD_SET需要用户扫描那些文件描述符就绪的范围。FD_SET是一个位图大小1024,可以在系统中更改上限。
第二个参数是读时间FDSET,第三个参数写事件FDSET,第四个异常事件FDSET,三四参数一般传NULL就行,最后一个超时时间,-1代表阻塞等待,0代表永不超时,大于0的值就是超时时间。
select返回-1代表异常,然后error number被设置。
select方法的跨平台性很好,可以支持很多平台。缺点一是可以监听的连接上限是1024,缺点二每一次都需要传入FDSET到内核中,上下文切换开销大。缺点三内核每次都返回被内核修改后的FDSET,每次都需要重置FDSET。缺点四不知道哪一个FD准备就绪,需要遍历所有的FDSET判断。
poll函数原型 int poll(struct pollfd fds, nfds_t nfds, int timeout);
第一个参数是一个pollfd结构体数组,第二个参数是fd数组的大小,第三个超时时间和select一样。
struct pollfd {
int fd; /
文件描述符 /
short events; /
需要监视的事件 /
short revents; /
已经发生的事件 */
};
revents字段内核修改,用户遍历pollfds数组然后判断revents处理事件后,修改为默认值,再重新返回给内核监听。
优点:1.突破了select的的文件描述符的上限。2.解决了select每一次都需要重置的缺点,只需要修改revents字段。
缺点:1.还是没有解决内核态到用户态上下文切换的开销,还是需要复制结构体数组。2.还是需要遍历结构体数组来处理就绪的事件。
epoll函数原型
相较于之前的两个方法,epoll有三个方法:
int epoll_create(int size);
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);
crate方法是创建一个可以监听size大小的epoll实例,现在size已经被弃用,传入的size只要大于0就可以了。
ctl方法可以对event_poll结构体上面的红黑树管理的fd进行添加删除和修改。
wait方法是一个阻塞方法,当有时间就绪的时候才返回,返回具体就绪事件的个数。
struct epoll_event {
__uint32_t events; /
Epoll events /
epoll_data_t data; /
User data variable */
};
typedef union epoll_data {
void *ptr;
int fd;
__uint32_t u32;
__uint64_t u64;
} epoll_data_t;
在epoll_create创建一个epoll实例的时候,内核中就创建了与之对应的event_poll结构体,该结构体包含主要的两个部分:rb_tree和rdlist双端队列。红黑树用来管理需要监听的事件列表。双端队列中就是已经就绪的事件。并且为每一个epitem注册的回调函数。当有事件准备就绪,内核先将红黑树的该节点根据回调方法添加到事件准备就绪队列,然后再返回给用户,用户通过epoll_wait返回的events数组拿到所有已经就绪的事件,并且开始处理。
epoll的优点:1.监听没有上限。2.不需要上下文的多次切换。3.不需要遍历监听的文件描述符,返回的是已经就绪的fd。

epoll还有两个不同的触发模式,LT(level triggered)水平触发和ET(edge triggered)边缘触发模式。
在水平触发模式下,只要条件满足(例如,缓冲区可读或可写),epoll_wait 就会不断返回该事件,直到应用程序显式地清除这些条件。
LT 模式类似于传统的 poll 行为,它会持续通知应用程序,直到应用程序读取或写入数据,改变了文件描述符的状态。
边缘触发模式在状态发生变化时只通知一次。例如,如果缓冲区可读,应用程序没有读取数据,那么在下一次 epoll_wait 调用时,不会再次收到该事件的通知,除非有新的数据到达。
ET 模式需要应用程序使用非阻塞 I/O 并正确处理返回事件,因为它只在状态改变时提供通知。

posted @ 2024-06-03 16:55  陈浩辉  阅读(29)  评论(0)    收藏  举报
ヾ(≧O≦)〃嗷~