Linux系统网络编程——第十九节 多路复用(1)(概念、select、poll)

简介: 等某事件就绪。即有数据可读或者可写的时候,或者达到一定的“水位线”的时候。

概念引出

我们来思考一个问题:



什么叫IO(input output)?


读取或者写入(IO)本质就是:等+拷贝。


读:等+将数据从内核空间(缓冲区)拷贝到用户空间(缓冲区)


写:等+将数据从用户空间(缓冲区)拷贝到内核空间(缓冲区)


等是在等什么呢?


等某事件就绪。即有数据可读或者可写的时候,或者达到一定的“水位线”的时候。


而高效IO即在IO的过程当中,尽可能减少等的比重。


那我们应当怎么促使高效IO呢?


我们有五种IO模型,分别是:


1、阻塞IO;


2、非阻塞IO;


3、信号驱动IO;(发送SIGIO,默认忽略)


4、多路复用,多路转接;


5、异步IO;


前四种都称之为同步IO。


我们之前用到的IO基本都是阻塞式IO。


我们下面所要学的select、poll、epoll做的就是一件事,就是等。


既然一个文件描述符等待结束的概率很小是固定的,那我就通过等待多个文件描述符的方式来去让其去减少等的比重


将一个阻塞式的文件描述符改成一个非阻塞的:(原型如下)


fcntl


函数原型如下.

#include <unistd.h>
#include <fcntl.h>
int fcntl(int fd, int cmd, ... /* arg */ );


传入的cmd的值不同, 后面追加的参数也不相同


实现函数SetNoBlock


基于fcntl, 我们实现一个SetNoBlock函数, 将文件描述符设置为非阻塞.

void SetNoBlock(int fd) {
    int fl = fcntl(fd, F_GETFL);
    if (fl < 0) {
        perror("fcntl");
        return;
    }
    fcntl(fd, F_SETFL, fl | O_NONBLOCK);
}



使用F_GETFL将当前的文件描述符的属性取出来(这是一个位图).


然后再使用F_SETFL文件描述符设置回去. 设置回去的同时, 加上一个O_NONBLOCK参数.


select

它的作用就是来等。

image.png

附fd_set的源码:

image.png



解释说明:老规矩,采用列点式。


1、第一个参数表示我所要等的所有的文件描述符的最大值加1.(注意不是个数+1,因为我们后面要传入位图)


2、最后一个参数:为等的方式:阻塞式等、非阻塞式等,设置某一段时间来去等


3、其返回值有三种形式:大于0表示已经有文件描述符就绪了;等于0表示超时了;小于0表示出错了


4、中间三个参数:表示读/写的文件描述符集,其是用一张位图来表示的。


5、以readfds为例,其既是输入型参数,又是输出型参数。输入的时候,表示告知OS需要关心哪些文件描述符上的读事件是否就绪。(其是一张位图,比如哪一个位置置为1,就表示该位置所对应的文件描述符就需要关心;即需要关心哪些位置上的读事件)


6、然后OS将上述所要关注的文件描述符进行轮询。在输出的时候,哪个位置为1,哪个位置所对应的文件描述符的文件读(写)事件就绪。


7、select结束之后,我们需要用这个readfds去检测哪个就绪了,然后需要对其进行重新设定。


8、注意:我们这里引入一个低水位线:即缓冲区里的最小字节数。


故select的本质方式就是在等,等待就绪事件的方式


注意:对位图的操作必须要用系统调用接口。因为不同的地方位图实现的方式可能不一样


select的特点

可监控的文件描述符个数取决于sizeof(fd_set)的值. 我这边服务器上sizeof(fd_set)= 512,每bit表示一个文件描述符,则我服务器上支持的最大文件描述符是512*8=4096.


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


一是用于再select 返回后, array作为源数据和fd_set进行FD_ISSET判断。


二是select返回后会把以前加入的但并无事件发生的fd清空,则每次开始select前都要重新从array取得fd逐一加入(FD_ZERO最先),扫描array的同时取得fd最大值maxfd,用于select的第一个参数。


备注: fd_set的大小可以调整,可能涉及到重新编译内核. 感兴趣的同学可以自己去收集相关资料.



select缺点

1、每次调用select, 都需要手动设置fd集合, 从接口使用角度来说也非常不便.


2、每次调用select,都需要把fd集合从用户态拷贝到内核态,这个开销在fd很多时会很大


同时每次调用select都需要在内核遍历传递进来的所有fd,这个开销在fd很多时也很大


select支持的文件描述符数量太小,为有限个


poll

就绪事件通知函数


poll主要是解决了select的两个问题:


1、poll没有上限;


2、输入输出含义让分离(采用两个变量)



timeout如果为0,表示以非阻塞方式等待,如果为-1,表示为永久阻塞方式;如果为一个常数,那就是具体常数的等待的时间。


第一个参数是一个结构体数组;


第二个参数表示该结构体数组里面的元素个数


关于该结构体:


第一个参数表示关注文件描述符。


第二个参数和第三个参数分别是用户->内核、内核->用户 关心该描述符的哪方面以及是否就绪


那么事件具体又指什么呢?

image.png


其选项和read、open的参数类似,采用的是(多标志位,直接按位或)


【poll实验】

运行截图:




一种用poll监听的伪代码

image.png


注意:

image.png

poll中监听的文件描述符数目增多时,和select函数一样, poll返回后,需要轮询pollfd来获取就绪的描述符。每次调用poll都需要把大量的pollfd结构从用户态拷贝到内核中.


同时连接的大量客户端在一时刻可能只有很少的处于就绪状态, 因此随着监视的描述符数量的增长, 其效率也会线性下降.



好啦,本节的内容就到这里啦~~


目录
相关文章
|
1月前
|
机器学习/深度学习 算法 机器人
【PID】基于人工神经网络的PID控制器,用于更好的系统响应研究(Matlab&Simulink代码实现)
【PID】基于人工神经网络的PID控制器,用于更好的系统响应研究(Matlab&Simulink代码实现)
174 15
|
1月前
|
机器学习/深度学习 数据采集 传感器
具有多种最大功率点跟踪(MPPT)方法的光伏发电系统(P&O-增量法-人工神经网络-模糊逻辑控制-粒子群优化)之使用粒子群算法的最大功率点追踪(MPPT)(Simulink仿真实现)
具有多种最大功率点跟踪(MPPT)方法的光伏发电系统(P&O-增量法-人工神经网络-模糊逻辑控制-粒子群优化)之使用粒子群算法的最大功率点追踪(MPPT)(Simulink仿真实现)
122 0
|
2月前
|
数据采集 存储 算法
MyEMS 开源能源管理系统:基于 4G 无线传感网络的能源数据闭环管理方案
MyEMS 是开源能源管理领域的标杆解决方案,采用 Python、Django 与 React 技术栈,具备模块化架构与跨平台兼容性。系统涵盖能源数据治理、设备管理、工单流转与智能控制四大核心功能,结合高精度 4G 无线计量仪表,实现高效数据采集与边缘计算。方案部署灵活、安全性高,助力企业实现能源数字化与碳减排目标。
61 0
|
1月前
|
算法 安全 网络安全
【多智能体系统】遭受DoS攻击的网络物理多智能体系统的弹性模型预测控制MPC研究(Simulink仿真实现)
【多智能体系统】遭受DoS攻击的网络物理多智能体系统的弹性模型预测控制MPC研究(Simulink仿真实现)
|
1月前
|
XML JSON JavaScript
从解决跨域CSOR衍生知识 Network 网络请求深度解析:从快递系统到请求王国-优雅草卓伊凡
从解决跨域CSOR衍生知识 Network 网络请求深度解析:从快递系统到请求王国-优雅草卓伊凡
63 0
从解决跨域CSOR衍生知识 Network 网络请求深度解析:从快递系统到请求王国-优雅草卓伊凡
|
4月前
|
安全 网络协议 Linux
Linux网络应用层协议展示:HTTP与HTTPS
此外,必须注意,从HTTP迁移到HTTPS是一项重要且必要的任务,因为这不仅关乎用户信息的安全,也有利于你的网站评级和粉丝的信心。在网络世界中,信息的安全就是一切,选择HTTPS,让您的网站更加安全,使您的用户满意,也使您感到满意。
139 18
|
2月前
|
存储
WGLOG日志管理系统可以采集网络设备的日志吗
WGLOG日志审计系统提供开放接口,支持外部获取日志内容后发送至该接口,实现日志的存储与分析。详情请访问:https://www.wgstart.com/wglog/docs9.html
|
4月前
|
NoSQL Linux 编译器
GDB符号表概念和在Linux下获取符号表的方法
通过掌握这些关于GDB符号表的知识,你可以更好地管理和理解你的程序,希望这些知识可以帮助你更有效地进行调试工作。
201 16
|
4月前
|
Linux 数据安全/隐私保护
使用Linux命令行接入无线网络Wi-Fi的示例。
现在,你已经使用命令行成功地连接到 Wi-Fi 网络了。这两个示例涵盖了用 `nmcli` 和 `wpa_supplicant` 连接无线网络的常见场景,让你能够不依赖图形化界面来完成这个任务。在日常使用中熟练掌握这些基本操作能增强你对 Linux 系统的理解,帮助你更有效地处理各种问题。
204 12
|
3月前
|
存储 Linux Shell
Linux进程概念-详细版(二)
在Linux进程概念-详细版(一)中我们解释了什么是进程,以及进程的各种状态,已经对进程有了一定的认识,那么这篇文章将会继续补全上篇文章剩余没有说到的,进程优先级,环境变量,程序地址空间,进程地址空间,以及调度队列。
72 0