【面试八股总结】Linux系统下的I/O多路复用

参考资料 :小林Coding、阿秀、代码随想录

        I/O多路复用是⼀种在单个线程或进程中处理多个输入和输出操作的机制。它允许单个进程同时监视多个文件描述符(通常是套接字),一旦某个描述符就绪(一般是读就绪或者写就绪),能够通知程序进行相应的读写操作。

        I/O多路复用允许在⼀个线程中处理多个I/O操作,避免了创建多个线程或进程的开销。

一、SELECT

        select是⼀个最古老的I/O多路复⽤机制,它可以监视多个⽂件描述符的可读、可写和错误状态,但是它的效率可能随着监视的文件描述符数量的增加而降低。

实现方式:

        select 将已连接的 Socket 都放到一个文件描述符集合,然后调用 select 函数将文件描述符集合拷贝内核里,让内核来检查是否有事件产生,检查的方式就是通过遍历文件描述符集合的方式,当检查到有事件产生后,将此 Socket 标记为可读或可写, 接着再把整个文件描述符集合拷贝用户态里,然后用户态还需要再通过遍历的方法找到可读或可写的 Socket,然后再对其处理。 

相关函数:

#include <sys/select.h>
int select(int nfds, fd_set* readfds, fd_set* writefds, fd_set* exceptfds, struct timeval* timeout);
- 参数:- nfds : 委托内核检测的最大文件描述符的值 + 1- readfds : 要检测的文件描述符的读的集合,委托内核检测哪些文件描述符的读的属性- 一般检测读操作- 对应的是对方发送过来的数据,因为读是被动的接收数据,检测的就是读缓冲区- 是一个传入传出参数- writefds : 要检测的文件描述符的写的集合,委托内核检测哪些文件描述符的写的属性- 委托内核检测写缓冲区是不是还可以写数据(不满的就可以写)- exceptfds : 检测发生异常的文件描述符的集合- timeout : 设置的超时时间struct timeval {long tv_sec; /* seconds */long tv_usec; /* microseconds */};- NULL : 永久阻塞,直到检测到了文件描述符有变化- tv_sec = 0 tv_usec = 0, 不阻塞- tv_sec > 0 tv_usec > 0, 阻塞对应的时间
- 返回值 :- -1 : 失败- >0(n) : 检测的集合中有n个文件描述符发生了变化
// 将参数文件描述符fd对应的标志位设置为0
void FD_CLR(int fd, fd_set *set);// 判断fd对应的标志位是0还是1, 返回值 : fd对应的标志位的值,0,返回0, 1,返回1
int FD_ISSET(int fd, fd_set *set);// 将参数文件描述符fd 对应的标志位,设置为1
void FD_SET(int fd, fd_set *set);//  fd_set一共有1024 bit, 全部初始化为0
void FD_ZERO(fd_set *set);

缺      点:

  1. 每次调用select,都需要把fd集合从用户态拷贝到内核态,这个开销在fd很多时会很大
  2. 同时每次调用select都需要在内核遍历传递进来的所有fd,这个开销在fd很多时也很大
  3. select支持的文件描述符数量太小了,默认是1024
  4. fds集合不能重用,每次都需要重置(因为内核会修改发生事件的fd)

二、POLL

     poll是select的⼀种改进,使用轮询方式来检查多个文件描述符的状态,避免了select中文件描述符数量有限的问题。但对于大量的文件描述符,poll的性能也可能变得不够⾼效。

改  进  点:

  1. 基于结构体数组存储要监视的文件描述符,文件描述符数量不受限制,可以处理任意数量的文件描述符;
  2. 结构体中使用revents作为是否发生事件标志,每次遍历只需要将revernts恢复为0,因此文件描述符集合可以重用。
#include <poll.h>
struct pollfd {int fd; /* 委托内核检测的文件描述符 */short events; /* 委托内核检测文件描述符的什么事件 */short revents; /* 文件描述符实际发生的事件 */
};struct pollfd myfd;
myfd.fd = 5;
myfd.events = POLLIN | POLLOUT;

函数原型:

int poll(struct pollfd *fds, nfds_t nfds, int timeout);
- 参数:- fds : 是一个struct pollfd 结构体数组,这是一个需要检测的文件描述符的集合- nfds : 这个是第一个参数数组中最后一个有效元素的下标 + 1- timeout : 阻塞时长0 : 不阻塞-1 : 阻塞,当检测到需要检测的文件描述符有变化,解除阻塞>0 : 阻塞的时长
- 返回值:-1 : 失败>0(n) : 成功,n表示检测到集合中有n个文件描述符发生变化

缺      点:

  1. 每次调用poll时,仍然需要将pollfd集合从用户态拷贝到内核态;
  2. 每次调用poll时,都需要在内核遍历传递进来的所有pollfd。

三、EPOLL

        EPOLL是Linux特有的I/O复用函数。epoll 使用⼀个事件驱动(event-driven)的方式来处理I/O操作,它只会返回就绪的文件描述符,而不是遍历整个文件描述符集合。

        epoll使用一组函数完成任务,而不是一个函数,并且epoll把用户关心的文件描述符上的事件放在内核里的一个事件表中,不需要像select和poll一样每次调用都需要重复传入文件描述符集合。但epoll需要一个额外的文件描述符,用于唯一标识内核中的事件表。

相关函数:

include <sys/epoll.h>
// 创建一个新的epoll实例。在内核中创建了一个数据,这个数据中有两个比较重要的数据,
// 一个是需要检测的文件描述符的信息(红黑树),
// 还有一个是就绪列表,存放检测到数据发送改变的文件描述符信息(双向链表)。
int epoll_create(int size);- 参数:size : 目前没有意义了。随便写一个数,必须大于0- 返回值:-1 : 失败> 0 : 操作epoll实例的文件描述符
// 对epoll实例进行管理:添加文件描述符信息,删除信息,修改信息
int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);- 参数:- epfd : epoll实例对应的文件描述符- op : 要进行什么操作EPOLL_CTL_ADD: 添加EPOLL_CTL_MOD: 修改EPOLL_CTL_DEL: 删除- fd : 要检测的文件描述符- event : 检测文件描述符什么事情struct epoll_event {uint32_t events; /* Epoll events */epoll_data_t data; /* User data variable */};常见的Epoll检测事件:    - EPOLLIN    - EPOLLOUT    - EPOLLERR
// 检测函数
int epoll_wait(int epfd, struct epoll_event *events, int maxevents, int timeout);- 参数:- epfd : epoll实例对应的文件描述符- events : 传出参数,保存了发送了变化的文件描述符的信息- maxevents : 第二个参数结构体数组的大小- timeout : 阻塞时间- 0 : 不阻塞- -1 : 阻塞,直到检测到fd数据发生变化,解除阻塞- > 0 : 阻塞的时长(毫秒)- 返回值:- 成功,返回发送变化的文件描述符的个数 > 0- 失败 -1

LT和ET模式:

        epoll 支持两种事件触发模式,分别是边缘触发(edge-triggered,ET水平触发(level-triggered,LT

  • 使用边缘触发模式时,当被监控的 Socket 描述符上有可读事件发生时,服务器端只会从 epoll_wait 中苏醒一次,即使进程没有调用 read 函数从内核读取数据,也依然只苏醒一次,因此我们程序要保证一次性将内核缓冲区的数据读取完
  • 使用水平触发模式时,当被监控的 Socket 上有可读事件发生时,服务器端不断地从 epoll_wait 中苏醒,直到内核缓冲区数据被 read 函数读完才结束,目的是告诉我们有数据需要读取;

        ET(edge - triggered)是高速工作方式,只支持 no-block socket。在这种模式下,当描述符从未就绪变为就绪时,内核通过epoll告诉你。然后它会假设你知道文件描述符已经就绪,并且不会再为那个文件描述符发送更多的就绪通知,直到你做了某些操作导致那个文件描述符不再为就绪状态了。但是请注意,如果一直不对这个 fd 作 IO 操作(从而导致它再次变成未就绪),内核不会发送更多的通知(only once)。

        ET 模式在很大程度上减少了 epoll 事件被重复触发的次数,因此效率要比 LT 模式高。epoll工作在 ET 模式的时候,必须使用非阻塞套接口,以避免由于一个文件句柄的阻塞读/阻塞写操作把处理多个文件描述符的任务饿死。

EPOLLONESHOT事件:

        即使使用ET模式,一个socket上的某个事件还是可能被触发多次。这在并发程序中会引起一个问题,假设一个线程在读取完某个socket上的数据后开始处理该数据,而在数据处理过程中该socket又有新的数据可读(EPOLLIN再次被触发),此时另一个线程被唤醒来读取这些新的数据,于是就出现了两个线程同时操作一个socket的局面。

        我们期望一个socket连接在任何时候都只被一个线程处理,可以采用EPOLLONESHOT事件实现。对于注册了EPOLLONESHOT事件的文件描述符,操作系统最多触发其上注册的一个可读、可写或者异常事件,且只触发一次,除非使用epoll_cnt函数重置改文件描述符上注册的EPOLLONESHOT事件。

SELECT、POLL和EPOLL区别:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/640366.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

SLS 查询新范式:使用 SPL 对日志进行交互式探索

作者&#xff1a;无哲 引言 在构建现代数据和业务系统的过程中&#xff0c;可观测性已经变得至关重要&#xff0c;日志服务&#xff08;SLS&#xff09;为 Log/Trace/Metric 数据提供了大规模、低成本、高性能的一站式平台服务&#xff0c;并提供数据采集、加工、投递、分析、…

前端点击按钮触发复制文本

1. 效果展示&#xff1a; 点击复制小图标进行内容的复制 在这里我们先不考虑适用插件的情况&#xff0c;因为如果只是简单的复制&#xff0c;则不需要插件 2. 绑定事件 这里我们以vue为例子&#xff0c; 原生和react我后面补上 <i slot"prefix" class"i…

JAVA基础之垃圾收集器

一 JVM垃圾收集 分代收集思想 当前虚拟机的垃圾收集一般采用分代收集算法&#xff0c;这种算法本身没有创新性&#xff0c;只是根据对象存活周期的不同将内存分为几块。一般将java堆内存分为新生代和老年代&#xff0c;这样我们就可以根据不同年龄到的特点选择不同的垃圾收集…

JavaScript作用域

一&#xff0c;作用域 就是代码名字&#xff08;变量&#xff09;在某个范围起作用和效果 1.全局作用域 整个script标签 &#xff0c;或一个js文件 2.局部作用域&#xff08;函数作用域&#xff09; 这个名字只在函数内部起作用和效果 二&#xff0c;变量作用域 1.全局变…

实战 | 无视杀软使用远控工具进行横向移动Tips

实战 | 无视杀软使用远控工具进行横向移动Tips。 在有杀软拦截&#xff0c;CS无法上线的情况下&#xff0c;经常用到todesk和向日葵这两个远控工具进行横向移动。不过这两个工具现在好像不怎么好用了。不过无所谓&#xff0c;用其他的就是了&#xff0c;听说最近GotoHTTP很火&…

PLC_博图系列☞P_TRIG:扫描 RLO 的信号上升沿

PLC_博图系列☞P_TRIG&#xff1a;扫描 RLO 的信号上升沿 文章目录 PLC_博图系列☞P_TRIG&#xff1a;扫描 RLO 的信号上升沿背景介绍P_TRIG&#xff1a; 扫描 RLO 的信号上升沿说明参数示例 关键字&#xff1a; PLC、 西门子、 博图、 Siemens 、 P_TRIG 背景介绍 这是一…

展商企业【广东伟创科技开发有限公司】| 2024水科技大会暨技术装备成果展

企业介绍 广东伟创科技开发有限公司成立于2006年&#xff0c;位于广东省江门市。公司是华南理工大学造纸与污染控制国家工程研究中心科技成果转化单位&#xff1b;是华南理工大学产学研合作单位&#xff1b;是广东省高新技术企业&#xff1b;是江门市现代信息服务业重点企业&am…

路由策略实验

一.实验要求 1、按照图示配置 IP 地址&#xff0c;R1&#xff0c;R3&#xff0c;R4 上使用 loopback 口模拟业务网段 2.R1 和 R2 运行 RIPV2在 RIP R2&#xff0c;R3 和 R4运行 OSPF&#xff0c;各自协议内部互通 3.在RIP和 OSPF 间配置双向路由引入&#xff0c;要求除 R4 上…

Macs Fan Control Pro for Mac:全面优化Mac风扇控制软件

Macs Fan Control Pro for Mac是一款专为苹果电脑用户设计的风扇控制软件&#xff0c;旨在通过精确的风扇速度调节&#xff0c;全面优化Mac的散热性能&#xff0c;确保系统始终运行在最佳状态。 Macs Fan Control Pro for Mac中文版下载 该软件具备实时监控功能&#xff0c;能够…

让流程图动起来

我们平时画流程&#xff0c;然后贴到文档&#xff0c;就完事了。但是过程演示的时候&#xff0c;如果只是一张静态图&#xff0c;很难吸引到听众的注意力&#xff0c;表达效果并不太好。常用的方法是可以用PPT进行动态演示&#xff0c;做PPT也是需要花一些时间&#xff0c;同时…

kaggle 泰坦尼克使用xgboost 得分0.73684

流程 导入所要使用的包引入kaggle的数据集csv文件查看数据集有无空值填充这些空值提取特征分离训练集和测试集调用模型 导入需要的包 import pandas as pd import numpy as np import matplotlib.pyplot as plt import seaborn as sns import warnings warnings.filterwarni…

百度AI大会发布的APP Builder和Agent Builder有什么区别

百度在AI大会发布了三款AI工具&#xff0c;包括智能体开发工具AgentBuilder、AI原生应用开发工具AppBuilder、各种尺寸的模型定制工具ModelBuilder 有很多人就问&#xff0c;APP Builder和Agent Builder有什么不一样&#xff0c;怎么那么多builder? 你们就这么理解&#xff…