socket编程之 select、poll、kqueue、epoll


函数参数numfds:文件描述符的最大值+1(为了限制检测文件描述符的范围)readfds:包含所有因为状态变为可读而触发select函数返回文件描述符writefds:包含所有因为状态变为可写而触发select函数返回文件描述符exceptfds:包含所有因为状态发生特殊异常而触发select函数返回文件描述符timeout:表示阻塞超时时限返回值当为-1的时候表示出错当为0的时候表示超时当大于0则成功基本思路,把要检测的文件描述符加载到fd_set类型的集合中,然后调用select函数检测加载到集合中的文件描述符;select函数监视的文件描述符分为3类,分别是writefds, readfds, exceptfds,调用之后select函数就会阻塞,直到有文件描述符就绪(有数据可读,可写或者except),或者超时(timeout指定等待时间,如果立即返回设为null即可),函数返回;当select函数返回之后,可以通过遍历fdset来找到就绪的描述符。这个代码中有不完善的地方:使用数组保存套接字,建议以链表的形式保存链表会更好一些;优点:跨平台缺点:单个进程能够监视的文件描述符的数量存在最大限制,在Linux上一般为1024,可以通过修改宏定义甚至重新编译内核的方式提升这个限制,但是这样也会造成效率的降低;每次都要调用 select ,都需要把fd集合从用户态拷贝到内核态,在fd很多时开销会很大;每次调用 select 都需要在内核遍历传递进来的所有fd,在fd很多时开销也很大;注意,每次调用select之前都要对fdset集合进行 FD_ZERO(&fdset) 操作,即清空。参考文章
linux的I/O复用技术函数参数:表示一个pollfd结构的数组。用来保存想要监听的文件描述符及其注册(绑定)的相应事件表示监听事件集合的大小指定poll的超时值。当timeout为-1时,就会一直阻塞,直到某个事件发生;当timeout为0时,表示立即返回。返回值:当为-1的时候表示失败,当为0的时候表示超时,当为大于0的整数的时候表示执行成功,表示文件描述符的个数。不同与select使用三个位图来表示三个fdset的方式,poll使用一个 pollfd的指针实现。该结构里包含了要监视等待的event和实际发生的event;经常检测的事件标记:POLLIN/POLLRDNORM:可读POLLOUT/POLLWRNORM:可写POLLERR:出错合法的事件标记如下:POLLIN: 有数据可读POLLRDNORM: 有普通数据可读POLLRDBAND: 有优先数据可读POLLPRI: 有紧迫数据可读POLLOUT: 写数据不会导致阻塞POLLWRNORM: 写普通数据不会导致阻塞POLLWRBAND: 写优先数据不会导致阻塞POLLMSG SIGPOLL: 消息可用POLLIN | POLLPRI等价于select()的读事件,POLLOUT |POLLWRBAND等价于select()的写事件。POLLIN等价于POLLRDNORM |POLLRDBAND,而POLLOUT则等价于POLLWRNORM。从原理上看,selectpoll都需要在返回以后,通过遍历文件描述符来获取已经就绪的socket。但是和select不同的是,调用这个函数后,系统不用清空它所检测的socket描述符集合;因此select函数适合于只检测少量socket描述符的情况,而poll函数适合于大量socket描述符的情况;生成一个内核事件队列,返回该队列的文件描述符,其它API通过这个描述符操作这个kqueue,结构如下:提供向内核注册/反注册事件和返回就绪事件或错误事件;在一个kqueue中,{ident,filter}确定一个唯一的事件;函数参数:kq:kqueue的文件描述符changelist:注册/反注册的事件数组nchanges:changelist的元素个数eventlist:满足条件的通知事件数组nevents:eventlist的元素个数timeout:等待事件到来时的超时时间返回值为可用事件的个数kqueue不光能够处理socket的事件,同时还能处理异步io,信号,文件变化等等;kqueue有两个部分,分别是kqueue和kevent;kqueue主要是用来描述event的队列,而kevent则是监听的事件;通过kevent提供三个主要的行为功能,分别是注册/反注册注意kevent中的neventlist这个输入参数,当其设为0,且传入合法的changelist和nchanges,就会将changelist中的事件注册到 kqueue 中;允许/禁止过滤器事件通过flags EV_ENABLE 和 EV_DISABLE使过滤器事件有效或者无效,这个功能在使用EVFILT_WRITE发送数据时非常有用;等待事件通知将nchangelist 和 nchanges设置成null和0,当kevent非错误和超时返回时,在eventlist和nevents中保存可用事件集合。和前面不同的是,kqueue不会像select或者poll一样每隔一段事件就去轮询所有的socket,当socket数量很多,但是很多socket都不活跃的时候,性能是有影响的,而kqueue只会关注事件发生的socket;创建事件表创建一个epoll的句柄,参数 size 并不是限制了epoll所能监听的描述符最大个数,只是对内核初始分配内部数据结构的建议,不同于select中的给出最大监听的fd+1。操作事件表函数参数epfd:事件表的文件描述符op:何种操作,包括EPOLL_CTL_ADD,EPOLL_CTL_DEL,EPOLL_CTL_MOD,分别实现对fd的监听事件进行添加、删除、修改fd:需要监听的文件描述符event:告诉内核需要监听什么事epoll_event 结构如下:监听相应事件函数参数:epfd:事件表的文件描述符events:从内核得到事件的集合maxevents:事件集合的大小(不能大于创建时的size)timeout:超时时间 epoll对文件描述符的操作有两种模式:LT(level trigger)和ET(edge trigger)。LT模式是默认模式,LT模式与ET模式的区别如下:
 LT模式:当epoll_wait检测到描述符免费云主机域名事件发生并将此事件通知应用程序,应用程序可以不立即处理该事件。下次调用epoll_wait时,会再次响应应用程序并通知此事件。ET模式:当epoll_wait检测到描述符事件发生并将此事件通知应用程序,应用程序必须立即处理该事件。如果不处理,下次调用epoll_wait时,不会再次响应应用程序并通知此事件。ET模式在很大程度上减少了epoll事件被重复触发的次数,因此效率要比LT模式高。epoll工作在ET模式的时候,必须使用非阻塞套接口,以避免由于一个文件句柄的阻塞读/阻塞写操作把处理多个文件描述符的任务饿死。当使用epoll的ET模型来工作时,当产生了一个EPOLLIN事件后, 读数据的时候需要考虑的是当recv()返回的大小如果等于请求的大小,那么很有可能是缓冲区还有数据未读完,也意味着该次事件还没有处理完,所以还需要再次读取:有时候epoll不一定比select和poll的效率高,比如这样的场景下:当活动连接数比较高的时候此时epoll会经常触发回调函数 ,此时在性能上还是有一定的损失.epoll适用于连接数量多,但是活跃的连接少.

相关推荐: Linux cut命令怎么使用

这篇文章主要介绍“Linux cut命令怎么使用”,在日常操作中,相信很多人在Linux cut命令怎么使用问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Linux cut命令怎么使用”的疑惑有所帮助!接下来,请跟着小编一起来学…

免责声明:本站发布的图片视频文字,以转载和分享为主,文章观点不代表本站立场,本站不承担相关法律责任;如果涉及侵权请联系邮箱:360163164@qq.com举报,并提供相关证据,经查实将立刻删除涉嫌侵权内容。

(0)
打赏 微信扫一扫 微信扫一扫
上一篇 01/27 10:50
下一篇 01/27 11:04