现在的位置: 首页 > 自动控制 > 工业·编程 > 正文

I/O复用三种API的比较

2017-06-14 11:21 工业·编程 ⁄ 共 1936字 ⁄ 字号 暂无评论

I/O复用虽然可以同时监听多个文件描述符,但他本身是阻塞的。并且,当多个文件描述符同时就绪时,如果不采用额外的措施,程序就只能按顺序依次处理其中的每一个文件描述符,这样I/O复用看起来就像是串行的,要实现并法就需要用多进程或多线程实现。

select  poll  epoll  比较

1:事件集

select的参数没有将文件描述符单独与事件绑定,而是用文件描述符的集合fd_set中的每一位代表文件描述符,0/1代表事件是否发生。所以需要三个fd_set分别传入可读,可写,异常事件,所以限制了select只能处理这三种事件类型的事件,并且限制了select只能监听文件描述符的个数是1024个且最大文件描述符的值是1023(可以修改但是不建议修改);另外,内核每次修改的就是用户传入的fd_set,所以下次调用select前需要重置这三个fd_set结构。

poll将文件描述符与事件单独定义且绑定在pollfd结构中,所以不受结构限制,用户自己定义监听事件的个数,可以开到32位(int型)的大小,但是往往系统的文件描述符达不到这么大,所以可以监听系统最大可维护的描述符大小;而且在pollfd中将监测事件和就绪事件分开了,这样就保证了events不被改变,因此pollfd不需要重置pllfd结构中的events成员;另外,poll中的可处理的事件也增加了,不止可读,可写,异常。

epoll在内核中维护了一个事件表(红黑树),因为是红黑树所以是可以扩展的,所以可以监听的文件描述符的个数也是不限制的;epoll返回的就绪事件也是和监测事件分开的,所以epoll调用前也无需重置监测事件;epoll可以处理的事件与poll的差不多,只是额外多了两个事件EPOLLET和EPOLLONESHOT。

2:关于拷贝

从用户拷贝到内核:select和poll都是用户定义的结构将用户关注的事件拷贝给内核让内核进行监听;epoll是直接创建的内核事件表,通过映射直接操作,省去了一次由用户到内核的拷贝。

从内核到用户:select和poll都是将内核中所有就绪的与未就绪的文件描述符都拷贝给用户传入的结构(只是poll拷贝给revents,和用户监测的分离开);但是epoll通过epoll_wait也会从内核拷贝给用户定义的struct epoll_event结构,但是只拷贝就绪的文件描述符;另外epoll是通过内核用与用户空间mmap同一块内存实现的,所以还epoll就减少了一些不必要的拷贝

3:应用程序索引就绪文件描述符的时间复杂度

第二点可以看出,select和poll将就绪的和未就绪的文件描述符都返回了,那么用户在检测的时候就需要使用循环探测那个文件描述符就绪,即索引就绪文件描述符的时间复杂度为O(n)。但是epoll只返回就绪的文件描述符,那么时间复杂度即O(1)。

4:工作模式

select和poll都只能处在相对低效的LT模式,而epoll可以处于ET高效模式。

5: 具体实现

select底层是用数组来维护,poll底层是链表维护,而epoll底层是红黑树,且不说其他就可以断定epoll的查找效率比较高!另外select和poll采用的都是轮询的方式,每次都要扫描整个事件集合,才能找到就绪事件的文件描述符。而epoll采用的是callback(回调机制),只要内核检测到就绪事件,就触发回调机制将就绪事件存储在就绪链表中最后写到用户空间。所以当你拥有一个很大的socket集合,不过由于网络延时,任一时间只有部分的socket是"活跃"的,但 是select/poll每次调用都会线性扫描全部的集合,导致效率呈现线性下降。但是epoll不存在这个问题,它只会对"活跃"的socket进行操作---就是因为在内核实现中epoll是根据每个fd上面的callback函数实现的。所以只有"活跃"的socket才会主动的去调用 callback函数,其他idle状态socket则不会,所以epoll的I/O效率不会因为fd的增加而线性下降滴。

epoll效率高的原因

1.底层用红黑树维护一个事件集,用一个就绪队列来存放就绪事件,查找效率很高。

2.使用mmap(内存映射技术)加速内核与用户空间的消息传递,减少拷贝,提高效率

3.内核采用callback回调机制,激活这个文件描述符(将节点放到就绪队列中去)调用epoll_wait时就会被通知。

4.I/O效率不随fd数目的增加而线性下降。

ps:并不是所有情况epoll的效率都比poll高,当事件集里的大多数事件就绪的时候,epoll的回调是比较耗时的,这时就可能poll轮询效率更高了,所以epoll适用于连接很多,但是活动链接较少的情况

给我留言

留言无头像?