多路复用IO:select poll epoll
作者:互联网
select
Select(Max+1,&rset,null,null,null)是因为0~max是max+1。
过程:
- 将文件描述符收集过来,把bitmap从用户态拷贝到内核态,交给内核态判断那个有数据。Select是个阻塞函数,没有数据时会一直阻塞在select。如果有数据来,FD(对应的bitmap那一位)置位,然后select返回,O(n)判断哪一个被置位了,然后将那一位的数据读出来然后进行处理。
缺点:
- 1 bitmap默认大小是1024,虽然能调整,但仍有上线。
- 2 FDset不可重用,因为被内核修改过了,代码每次都要重新创建一个fdset。
- 3 从用户态切换到内核态的切换然后拷贝仍有开销。
- 4 O(n)遍历判断哪一个被置位了。
poll
Poll(pollfds,5(元素个数),50000(超时时间));
- 同样是从用户态拷贝到内核态,和select一样,好处是没有使用bitmap,strct pollfd{Int fdl short events; short revents;};
- event在意的事件(读写),poll也是阻塞函数,有被置位,置的是revents而不是fd,然后返回。O(n)个被置位了,然后将那一位的数据读出来然后进行处理,将revents重置为0。
改善的缺点就是没了bitmap的上限(pollfd设置元素个数)和revents可以重用。
epoll
没有revents字段
1 epfd = epoll_create(10); 创建白板
2 epoll_ctl(epfd, EPOLL_CTL_ADD, ev.data.f0, &e0); 在白板上写字
3 内核与用户共享epfd (通过mmap系统调用是共享的一种方式)
有数据置位,通过重排,将有数据的放到最前面的位置,返回触发了几个事件。这样只需要O(1)就可以遍历。
epoll只能工作在linux下!
epoll 水平触发(LT)与 边缘触发(ET)的区别?
- 水平触发(LT,Level Trigger):当文件描述符就绪时,会触发通知,如果用户程序没有一次性把数据读/写完,下次还会发出可读/可写信号进行通知。
- 边缘触发(ET,Edge Trigger):仅当描述符从未就绪变为就绪时,通知一次,之后不会再通知。
区别:边缘触发效率更高,减少了事件被重复触发的次数,函数不会返回大量用户程序可能不需要的文件描述符。
使用场景:当连接数较多并且有很多的不活跃连接时,epoll 的效率比其它两者高很多。当连接数较少并且都十分活跃的情况下,由于 epoll 需要很多回调,因此性能可能低于其它两者。
标签:触发,置位,epoll,bitmap,内核,IO,poll,select 来源: https://www.cnblogs.com/philo-zhou/p/14391754.html