IO多路复用(select、poll、epoll总结)

IO多路复用

原型介绍:

IO多路复用:这种方式可以同时监测多个文件描述符并且这个过程是阻塞的,一旦检测到有文件描述符就绪( 可以读数据或者可以写数据)程序的阻塞就会被解除,之后就可以基于这些(一个或多个)就绪的文件描述符进行通信了。通过这种方式在单线程/进程的场景下也可以在服务器端实现并发。常见的IO多路转接方式有:select、poll、epoll。

select函数原型:

入参:

(1)nfds:委托内核检测的这三个集合中最大的文件描述符 + 1

内核需要线性遍历这些集合中的文件描述符,这个值是循环结束的条件

在Window中这个参数是无效的,指定为-1即可

(2)readfds(读集合):文件描述符的集合, 内核只检测这个集合中文件描述符对应的读缓冲区

传入传出参数,读集合一般情况下都是需要检测的,这样才知道通过哪个文件描述符接收数据

(3)writefds(写集合):内核只检测这个集合中文件描述符对应的写缓冲区

如果不需要使用这个参数可以指定为NULL

(4)exceptfds(异常集合):内核检测集合中文件描述符是否有异常状态

(5)timeout:超时时长,用来强制解除select()函数的阻塞的

NULL:函数检测不到就绪的文件描述符会一直阻塞。

等待固定时长(秒):函数检测不到就绪的文件描述符,在指定时长之后强制解除阻塞,函数返回0

不等待:函数不会阻塞,直接将该参数对应的结构体初始化为0即可。

返回值:

大于0:成功,返回集合中已就绪的文件描述符的总个数

等于-1:函数调用失败

等于0:超时,没有检测到就绪的文件描述符

注:select()函数中第2、3、4个参数都是fd_set类型,它表示一个文件描述符的集合,这个类型的数据有128个字节,也就是1024个标志位,和内核中文件描述符表中的文件描述符个数是一样的。

也就是说select检测的文件描述符有限制1024

内核检测流程:

fd_set中存储了要委托内核检测读缓冲区的文件描述符集合

如果集合中的标志位为0代表不检测这个文件描述符状态

如果集合中的标志位为1代表检测这个文件描述符状态

内核检测读集合中文件描述符对应的读缓冲区若无数据,内核将该文件描述符对应标志位改为0,有数据标志位不变为1。

当select()函数解除阻塞之后,被内核修改过的读集合通过参数传出,此时集合中只要标志位的值为1,那么它对应的文件描述符肯定是就绪的,我们就可以基于这个文件描述符和客户端建立新连接或者通信了。

初始化集合函数

处理流程:

服务器端基于select实现并发:

(1)创建监听套接字lfd = socket();

  (2) 监听套接字lfd与本底IP及端口进行绑定,bind();

(3)监听套接字设置监听 listen();

(4)创建文件描述符集合fd_set,用于检测读事件;

通过 FD_ZERO() 初始化

通过 FD_SET() 将监听的文件描述符放入检测的读集合中

(5)循环调用select(),周期性检测

(6)select解除阻塞返回,得到满足就绪的文件描述符集合

通过FD_ISSET() 判断集合中的标志位是否为 1

如果这个文件描述符是监听的文件描述符,调用 accept() 和客户端建立连接

将得到的新的通信的文件描述符,通过FD_SET() 放入到检测集合中

如果这个文件描述符是通信的文件描述符,调用通信函数和客户端通信

如果客户端和服务器断开了连接,使用FD_CLR()将这个文件描述符从检测集合中删除

如果没有断开连接,正常通信即可。

(7)

poll函数

入参:(1)fds: struct pollfd类型的数组,存储待检测的文件描述符信息,三个成员

1.fd:检测的文件描述符

 2.Events:委托内核检测的fd事件(输入、输出、错误),每一个事件有多个取值

 3.revents:这是一个传出参数,数据由内核写入,存储内核检测之后的结果

(2)nfds: 这是第一个参数数组中最后一个有效元素的下标 + 1(也可以指定参数1数组的元素总个数)

(3)timeout:poll函数阻塞时长

-1:一直阻塞,直到检测的集合中有就绪的文件描述符(有事件产生)解除阻塞

0:不阻塞,不管检测集合中有没有已就绪的文件描述符,函数马上返回

大于0:阻塞指定的毫秒(ms)数之后,解除阻塞

返回值:失败: 返回-1

成功:返回一个大于0的整数,表示检测的集合中已就绪的文件描述符的总个数

缺点:

1.文件描述符数量有限,32位1024,64位2048;

2.采用轮询的方式,效率低

3.用户态与内核态频繁复制传递fd数据,开销大

poll与select区别:

三者对比:

共同点:一个线程管理和检测IO是否准备就绪。

三者相关API:

Select

Poll

epoll

区别

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值