I/O复用模型

本文深入解析I/O复用模型,包括select、poll和epoll三种方法。select受文件描述符数量限制,适用于小规模连接;poll无此限制但效率有限;epoll采用高效就绪队列和红黑树,实现高并发场景下优秀性能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

I/O复用模型

在这里插入图片描述

一、select 函数

select能监听的文件描述符受限于FD_SETSIZE,一般为1024,单纯的改变进程打开的文件描述符个数并不能改变select监听文件个数;解决1024以下客户端时使用select是很适合的,但如果链接客户端过多,select采用的是轮询模型,会大大降低服务器响应效率,不应在使用select。
在这里插入图片描述

nfds:监控的文件描述符里最大文件描述符加1,此参数会告诉内核检测前多少个文件描述符的状态
readfds:监控有读数据到达文件描述符集合,传入传出参数
writefds:监控写数据到达文件描述符集合,传入传出参数
exceptfds:监控异常到达文件描述符集合,带外数据到达异常,传入传出参数
timeout:定时阻塞监控时间,3种情况:
①:NULL,永远等下去
②:设置timeval,等待固定时间
③:设置timeval里时间均为0,检查描数字后立即返回,轮询

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

服务器端代码已经实现了 但是用傻瓜命令nc去ping服务器时 结果还正确,代码放文件夹里
在这里插入图片描述
在这里插入图片描述

二、poll函数
与select函数类似,不过没有监管文件描述符个数的限制。
在这里插入图片描述

①fds:指向一个结构体数组的第个元素指针,每个数组元素都是一个struct pollfd结构,用于指定测试给某个给定的fd的条件
②nfds:表示fds结构体数组的长度
③timeout:表示poll函数的超时时间,单位是毫秒
与select不一样,poll函数中第一个参数引入了pollfd 这个结构体的数组,数组中的每一个元素表示了要监管的套接字,这个结构体如下:
在这里插入图片描述

通过给pollfd 结构的fd成员赋值,同时设定好events参数,表示就把这个文件描述符加到poll函数的监管列表去了。Poll函数中的events参数,在指定单个文件描述符的时候就指定要监管的事件。
三、epoll函数
epoll使用过程分为3步:
①调用epoll_create创建一个epoll句柄(epoll对象);
②调用epoll_ctl函数对需要监控的文件描述符进行增删改;
③调用epoll_wait函数等待文件描述符就绪。
1.epoll_create():调用epoll_create函数,成功之后会返回一个文件描述符,这个文件描述符也就是创建出来的epoll对象,所以当用完之后需要调用close函数来关闭这个文件描述符,否则会导致文件描述符用尽。
①eoll_create函数调用epoll_create1函数,epoll_create1函数里面调用ep_alloc函数,ep_alloc函数会调用相关的函数初始化epoll对象的就绪队列(一个空的就绪队列,当某个文件描述符指定的事件发生时,就会将该文件描述符相应的信息放在该就绪队列中);
②ep_alloc函数还会调用相关函数初始化红黑树;
③epoll_create1函数还会调用 anon_inode_getfd()函数,该函数会分配一个空闲描述符,会创建一个匿名文件,将该空闲文件描述符与匿名文件相关联,该空闲文件描述符就是调用epoll_create函数成功后的返回值(也就是epoll对象);
在这里插入图片描述

2.epoll_ctl:对epoll对象epfd,对于文件描述符fd执行什么样的操作,可以将fd注册进epfd中,也可以删除epfd中的fd,还可以修改fd监听的事件。
在这里插入图片描述

epfd:是epoll_create函数创建的epoll对象
op:对该epfd的相关操作(三个取值:EPOLL_CTL_ADD;EPOLL_CTL_DEL;EPOLL_CTL_MOD)
fd:需要监听的文件描述符
event:是一个结构体的地址,该结构体用来告诉内核需要监听的事件是什么,需要监听的数据是什么类型的。
3.epoll_wait:收集在epfd中已经就绪的事件
在这里插入图片描述

events:这里的events是一个struct epoll_event的数组,该数组里面存放内核拷贝至用户空间中已经就绪的文件描述符相关信息,该数组的每个元素都是一个epoll_event的结构体
maxevents:表示events数组的大小
timeout:表示超时时间,以毫秒为单位,如果为0则不会阻塞立即返回,-1是永久阻塞
函数执行的操作:
①当用户调用epoll_wait函数时,用户需要自己传入一个epoll_event数组,以及该数组的大小,还会传入一个超时时间;
②epoll_wait函数首先会检查用户传入的参数是否合法(events数组是否可写,maxevents是否为有效大小);
③epoll_wait主要调用ep_poll函数获取事件,ep_poll函数会检查就绪队列是否为空,如果就绪队列为空,就将该进程加入到eventpoll的等待队列中,等待被回调函数唤醒或者到了超时时间,如果过了超时时间还没有被唤醒,epoll_wait函数也会返回,返回0,如果就绪队列不为空,就将就绪队列里面的事件拷贝至用户传入的events数组中,并且将就绪文件描述符的数量返回给用户。
④因为一次不会有多个文件描述符相应的事件就绪,也就是就绪队列不会很长,则内核将就绪队列中的内容拷贝至用户空间的时间复杂度接近于O(1),这也是epoll高效的体现。
⑤epoll_wait函数成功返回的是就绪的文件描述符的个数,也就是events数组里面有效内容的大小,通过遍历events数组,就可以得到相应的文件描述符和事件,根据不同的文件描述符就可以采取不同的操作。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值