概述
select、pool 、epoll剖析:I/O复用能使系统同时监听多个文件描述符
读事件 就绪(缓冲区有数据) 客户端发数据了缓冲区才有数据。
写事件 就绪(缓冲区没满)
异常:网络情况中,select能处理的异常情况只有一种,socket接收到外带数据。
select系统调用: | pool系统调用: |
1、用途:在一段时间内,监听用户感兴趣的的文件描述符上的可读、可写和异常事件。(轮询) | 1、同select,也是在指定时间内,轮询一定数量的文件描述符。以测试其中是否就绪者。(轮询:因为是数组所以需要一个一个的遍历) |
2、select API: int select(int nfds,fd_set *readfds,fd_set *writefds,fd_set *exceptfds,struct timeval * timeout); 从左到右参数依次为被监听的文件描述符的总数、可读、可写、异常事件对应的文件描述符的集合。 fd_set结构体仅包含一个整型数组,该数组的每个元素的每一位都标记了一个文件描述符。没有将文件描述符和事件绑定,不能处理更多类型的事件,另一方面由于内核对fd_set的在线修改,应用程序下次调用select得对这3个参数进行重置。 如果在超时时间内没有任何就绪事件则selet返回0.失败返回-1并设置errno值。 | 2、pool API: int poll(struct pollfd *fds,nfds_t nfds,int timeout); fds是一个pollfd结构类型的数组,他指定所有我们感兴趣的文件描述符的可读、可写、和异常事件等。(fds和下面的的fd意义不同fd是特定的)
poll系统返回值的意义和select相同。
fd成员指定文件描述符;events策划哪个院告诉poll监听fd上的哪些事件,它是一系列事件的按位或;revents则成员则有内核修改,已通知fd实际发生了哪些事件。将文件描述符和事件绑定,任何事件都被统一处理。并且每次内核修改的都是revents成员,events成员不变,下次调用poll时无需重置pollfd的事件集参数。 |
3、最多可处理1024个文件描述符,set结构体中有1024个位。这个位是由一个宏表示的。 | 3、处理的文件描述符比select多,最多有65536个 |
4、处理外带数据(可能要处理两种事件)
| poll的事件类型更具体一点。 |
5、例如去图书馆领书,一个人去领,轮到是给谁打电话,不用每个人都去等,只用最后去领。 | 5、大概思想同select. |
select:fd_set的整型数组共1024位 poll: pollfd结构数组最大65536
读事件 | 1 | 0 | 0 | 1 | 1 | 0 | 0 | ...... |
写事件 | 1 | 0 | 1 | 0 | 0 | 0 | 0 | ...... |
异常 | 0 | 1 | 0 | 1 | 1 | 1 | 1 | ...... |
select、和poll调用过程
epoll系统调用: |
实现:是linux特有的I/O复用函数。它在实现上和使用上与select和poll有着很大的差异。epoll使用一组函数来完成任务,而不是单个函数。epoll把用户关心的文件描述符上的事件放在一个内核事件表中。从而无需像select和poll那样每次调用都要重复传入文件描述符或者事件集。哪个描述符有事件就绪,内核通过回调函数将其添加到就绪队列。 |
所使用函数:
1、epoll需要一个额外的文件描述符,来唯一标识内核中的这个事件表。这个文件描述符使用如下函数创建。 int epoll_create(int size) size只是给内核一个提示,告诉它事件表需要多大。该函数返回的文件描述符将用作其他所有epoll系统调用的第一个参数,以指定要访问的内核事件表。 2、下面函数用来操作内核事件表: int epoll_ctl(int epfd,int op,int fd,struct epoll_event *event) (1)fd参数是要操作的文件描述符,op参数指定操作类型,有如下三种: (2)event参数指定事件,它是epll_event结构指针类型,定义如下: ①event成员描述事件类型。epoll支持的事件类型和poll基本相同。表示epoll事件类型的宏就是在poll相对应得宏前面加上“E”。epoll有两个额外的事件类型——EPOLLET和EPOLLONESHOT。他们对于epoll高效运作非常关键。 ②data用于存储用户数据。epoll_data_t的定义如下: 3、epoll系列系统调用的主要接口是epoll_wait函数。它在超时时间内等待一组文件描述符上的事件,原型如下: int epoll_wait(int epfd,struct epoll_event *events,int maxevents,int timeout) 该函数成功返回就绪文件描述符的个数,失败时返回-1并设置errno.maxevents指定最多监听多少个事件。 epoll_wait函数如果检测到事件,就将就绪的事件从内核事件表(epfd参数指定)复制到events指向的数组中。这个数组只用于输出epoll_wait检测到的就绪事件,而不像select和poll的数组参数那样即用于传入用户注册的事件,又输出内核检测到的事件。这就极大的提高了应用程序索引就绪 描述符的效率。 |
epoll_wait函数调用后就返回了所有的就绪文件描述符,而poll还需要遍历所有的已注册的文件描述符并找到其中的就就绪者。 |
2、epoll_ctl 添加 删除 修改
添加=》注册回调函数 epoll_poll_callback,当描述符上有数据就绪时,用设备驱动程序调用回调函数,将描述符和事件添加到就绪队列rdlist中。
3、当rdlist有数据时,将其拷贝到用户空间,就绪事件拷贝到用户空间,就绪事件个数.作为返回值,也就是拷到用户空间的数目。
ET模式与LT模式:select都只能工作于LT模式,而epoll可工作于LT模式和ET模式
LT | ET |
多次触发直至数据处理完成 | 只触发一次,比较高效。 |
| 若一个文件描述符上的数据比较多,那么当若采用LT模式的话,其他的文件描述符就不会被处理,所以ET比LT高效 |
LT:input:hello (一次只接受一个) ET :input:hello(一次只接受一个)
客户端(反复提醒)h h
e input:ad
l e
l
o
最后
以上就是大力啤酒为你收集整理的select、poll、epoll系统调用及ET与LT模式的全部内容,希望文章能够帮你解决select、poll、epoll系统调用及ET与LT模式所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复