来源:

【并发】IO多路复用select/poll/epoll介绍

select用法&原理详解(源码剖析)

======================================================================================================


=============================================================================================================================================================================================================================================================================================================================================

============================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================

《linux》之IO教程

int select(int maxfdp, fd_set *readfds, fd_set *writefds, fd_set *errorfds, struct timeval *timeout);

简单理解select模型

理解select模型的关键在于理解fd\_set,为说明方便,取fd\_set长度为1字节,fd\_set中的每一bit可以对应一个文件描述符fd。则1字节长的

fd\_set最大可以对应8个fd,fd\_set是一个bitmap;

(1)执行fd\_set set; FD\_ZERO(&set) ,则set用位表示是0000,0000。

(2)若fd=5,执行FD\_SET(fd,&set) ,后set变为0001,0000(第5位置为1),若再加入fd=2,fd=1,则set变为0001,0011

(4)执行select(6, &set, 0, 0, 0),阻塞等待

(5)若fd=1,fd=2上都发生可读事件,则select返回,此时set变为0000,0011。注意:没有事件发生的fd=5被清空。

所以,我们可以得到select模型的特点:
(1) 文件描述符个数有限,长度和系统内存有关。select使用位域的方式来传递关心的文件描述符,位域就有最大长度。

select使用位域的方式传回就绪的文件描述符,调用者需要循环遍历每一个位判断是否就绪,当文件描述符个数很多,但是空闲的文件描

述符大大多于就绪的文件描述符的时候,效率很低。

(2) 将fd加入select监控集的同时,还要再使用一个数据结构array保存放到select监控集中的fd,

开始 select前都要重新从array取得fd逐一加入(FD\_ZERO最先),扫描array的同时取得fd最大值maxfd,用于select的第一个参数。

在select 返回后,array作为源数据和fd\_set进行FD\_ISSET判断

select返回后会把以前加入的但并无事件发生的fd清空

(3) 可见select模型必须在select前循环array(加fd,取maxfd),select返回后循环array(FD\_ISSET判断是否有时间发生)。

为啥慢?

需要把 fd\_set 集合从用户态拷贝到内核态

调用 select 函数时,需要在内核遍历传递进来的所有 fd\_set

通知事件到来给用户进程,需要把整个 bitmap 拷到用户空间,让用户空间去查询。

不知道是哪些文件描述符有数据可以读写,需要把所有的文件描述符都轮询一遍才能知道。

标签: linux, set, 描述符, array, IO, select, FD, fd

相关文章推荐

添加新评论,含*的栏目为必填