【图解IO与Netty系列】IO多路复用

news2024/12/25 9:29:26

IO多路复用

  • 为什么要使用IO多路复用
  • Linux的IO多路复用接口
    • select
    • poll
    • epoll

为什么要使用IO多路复用

我们常用的IO模型是BIO,我们Java里的IO流大多数都是BIO,也就是同步阻塞式IO,这种IO操作的好处是简单方便,但是缺点也很明显——性能不高。

阻塞式IO的特点就是在数据未就绪前,要等待数据就绪。比如以网络IO为例,在客户端没有发送数据前,服务端调用read函数会阻塞等待客户端发送数据,当客户单发送的数据到达服务端网卡缓存区,并被DMA拷贝到操作系统内核时,服务端的用户线程才开始拷贝数据到用户空间。由于BIO是同步阻塞IO,这个“同步”就是把内核空间的数据拷贝到用户空间的这个工作由用户线程自己完成,在数据拷贝期间用户线程依然是阻塞的。

在这里插入图片描述

于是就有了NIO,NIO是同步非阻塞式IO,在客户端未发送数据前,服务端用户线程线程调用read()函数不会阻塞,而是马上返回一个error,用户线程可以先干点别的事情,然后再次尝试read(),如果此时数据就绪,那么read()函数会阻塞,用户线程把内核空间的数据拷贝到用户空间。

在这里插入图片描述

NIO比起BIO来说性能有所提供,在数据未就绪时不需要阻塞等待。由于数据未就绪时不会阻塞当前线程,因此把所有需要监听的Socket套接字收集到一个集合当中,当前线程可以轮询这个套接字集合,哪个套接字就绪就阻塞读取哪个套接字的数据。这样就由一个线程监听一个Socket变成一个线程监听多个Socket。

在这里插入图片描述

但是NIO需要用户线程不断轮询,这是非常消耗CPU资源的一种操作,效率也不高。我们应该让当前线程阻塞监听多个socket,如果有一个或多个socket就绪,当前线程才解阻塞,然后我们可以把就绪socket的读取操作提交给线程池执行,这样效率就得到提升。于是就是有了IO多路复用。

我们使用IO多路复用时,通常要先注册需要监听的socket文件描述符以及在该socket上关注的事件(读就绪事件、写就绪事件、连接就绪事件)。

在这里插入图片描述

操作系统内核会使用对应的数据结构保存注册进来的socket文件描述符,当对应的socket有事件就绪时,操作系统会通知阻塞的用户线程;用户线程接收到通知后会解阻塞,用户线程解阻塞后可以自己操作有事件就绪的Socket,也可以提交到线程池处理。

在这里插入图片描述

为什么IO多路复用会比BIO和NIO的性能高呢?原因有两点:

  • IO多路复用可以一个线程监听多个Socket。
  • IO多路复用的read操作都是有效的read,是收到操作系统内核的Socket已就绪通知时才发起的read操作,没有了等待数据就绪期间的阻塞。

Linux的IO多路复用接口

Linux提供的IO多路复用接口一共有select、poll、epoll三种。

在这里插入图片描述

select

int select (int n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval 
*timeout);

select函数向操作系统注册需要监听的文件描述符数组,数组最大上限被限制为1024(默认1024,可以修改),Linux操作系统内核会保存这个文件描述符数组。注册的数组分三个,分别是关注读就绪事件的readfds,关注写就绪事件的writefds,关注异常事件的exceptfds。

在这里插入图片描述

当调用select函数后,当前线程就处于阻塞状态。当数组中的某个或某几个socket有事件发生时,当前线程会解阻塞,然后当前线程需要遍历数组中的每一个socket文件描述符,判断它是否有事件发生。

在这里插入图片描述

使用select函数的IO多路复用是比BIO和NIO的性能高不少,但是存在两个缺点:

  • socket文件描述符数组长度有限制,意味着监听的socket有上限。
  • 当有socket就绪时,用户线程并不知道数组中哪些socket文件描述符就绪,需要遍历。

poll

int poll (struct pollfd *fds, unsigned int nfds, int timeout);

poll使用pollfd结构体存在需要监听的socket文件描述符以及关注的事件。

在这里插入图片描述

当前线程调用poll函数,会以pollfd数组的形式向操作系统内核注册需要监听的socket文件描述符。

在这里插入图片描述

调用了poll函数之后,当前线程阻塞。当某个或某几个pollfd中的socket文件描述符有事件就绪时,操作系统内核会通知当前线程,当前线程解阻塞。当前线程解阻塞之后,还是需要遍历pollfd数组,判断每一个pollfd是否关注的事件已就绪。

在这里插入图片描述

poll解决了select有监听socket文件描述符上限的问题,理论上poll可以监听无数个socket。但是与select一样,用户线程并不知道哪些socket就绪,还是需要遍历数组,因此效率还是有待提高。因此就有了epoll这种不需要遍历的IO多路复用接口。

epoll

int epoll_create(int size)int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event)int epoll_wait(int epfd, struct epoll_event * events, int maxevents, int timeout);

相比与select与poll接口的只有一个函数,epoll有三个函数——epoll_create、epoll_ctl、epoll_wait。

epoll_create创建一个epoll实例,epoll实例使用一个红黑树结构保存注册进来的socket文件描述符,然后使用一个链表保存就绪的socket文件描述符,此时epoll实例还是空的。

在这里插入图片描述

epoll_ctl函数则是向epoll实例添加需要监听的socket文件描述符以及关注的事件类型,socket描述符以及关注的事件类型被包装在epoll_event结构体中。

在这里插入图片描述

epoll_wait函数是阻塞等待注册到epoll实例的一个或多个文件描述符就绪。当epoll实例中的某个socket有事件就绪时,会把对应的epoll_event拷贝到epoll实例中的链表结构中。当用户线程调用epoll_wait函数时,如果epoll实例中的链表结构没有就绪的epoll_event时,会阻塞等待,如果epoll_event非空,则把这个链表拷贝到用户空间,此时用户线程就可以逐一处理链表中就绪的socket,无需遍历判断是否就绪。

在这里插入图片描述

epoll解决了监听的socket有上限和需要遍历判断socket是否就绪的两个问题,大大提供了Linux里IO多路复用的性能。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【技术实操】银河高级服务器操作系统实例分享,TCP长连接与短连接详细说明

1.服务器环境以及配置 物理机/虚拟机/云/容器 物理机 处理器: HUAWEI Kunpeng 920 具体操作系统版本 Kylin-Server-10-SP1-Release-Build20-20210518- aarch64 内核版本 kernel-4.19.90-23.8.v2101.ky10.aarch64 2.问题现象描述 对TCP长连接有疑问 1、如何…

Yolov8训练自己的数据集(脱离ultralytics库)

最近在整理关于yolov8的相关内容,有个很大的问题,抛开yolov8性能不谈,yolov8代码的使用灵活性不如yolov5,尤其是对于一些新手或者对yolo框架不是很熟悉的人(这也是因人而异,有些人可能会喜欢v8代码的使用方式)。比如在…

牛客网刷题 | BC94 反向输出一个四位数

目前主要分为三个专栏,后续还会添加: 专栏如下: C语言刷题解析 C语言系列文章 我的成长经历 感谢阅读! 初来乍到,如有错误请指出,感谢! 描述 将一个四位数&…

1.int 与 Integer 的简单区别

蓝桥杯刷题从此开始: 第一题就是两个数的和,个人看来主要考察 int与integer 的区别; 这是我提交的答案,竟然会报错: import java.util.*; //输入A、B,输出AB。 class add {public static void main(String …

MT7628原厂Uboot修改交互串口

工作中,遇到用户用Skylab的SKW92A模组,在参考设计时,将UART接口预留错的情况,对于这种情况,需要将原厂SDK默认的交互串口UART0,改为UART1。在开发过程中,经常需要在Uboot阶段升级固件&#xff0…

5.25机器人基础-空间描述和变换1

参考资料:《机器人学导论》John.J.Craig 彻底搞懂“旋转矩阵/欧拉角/四元数”,让你体会三维旋转之美_欧拉角判断动作-CSDN博客 机器人操作的定义是指通过某种机构使零件和工具在空间运动。因此,对于坐标系的定义显得尤为重要,相…

【docker】Docker的基本指令和HTML/PYTHON/C++的简单创建示例

目录 🌊1. 什么是 Docker? 🌊2. Docker 安装 🌊3. Docker基本指令 🌊4. Docker 创建示例【联网情况】 🌍4.1 示例:HTML 🌍4.2 示例:Python 脚本 🌍4.3…

log4j2远程代码执行

漏洞复现 漏洞复现2 这个框架不是web框架了,不是服务器web网站框架了,是java日志框架,就是记录日志信息,每一个程序都有一个日志文件,这个就是java里面记录日志的一个框架,它存在的点也是日志框架那几个代…

Python语法(全)

前言: 下面是Python基本的语法,大家耐心观看! 1.基础语法 1.1字面量 字面量:在代码中,被写下来的的固定的值,称之为字面 1.2字符串 字符串(string),又称文本&#xff…

防火墙——域网络、专用网络、公用网络

在防火墙设置中,域网络、专用网络和公用网络是指计算机连接到网络时所处的不同环境。每种环境都有不同的安全级别和配置。 1、域网络(宽松) 域网络是指计算机加入了一个Windows域(Domain)环境,这通常在企业…

v-rep---script-function

作用,实现,参数讲解。 script-function标签 作用 问题:如何在插件的接口中调用lua脚本中定义的函数? 用于声明一个函数,这个函数的作用是通过v-rep提供的接口sim::callScriptFunctionEx()调用脚本的函数&#xff0…

用AI比赛助手降维打击数学建模,比赛过程详细介绍,这保研不就稳了吗

数学建模是个小众的赛道,可能很多大学生不知道,简单来说:他能薅学分、保研加分、毕业好找工作(简历上写一辈子),尤其是基于GPT-4o模型,简直对他们是降维打击。 数学建模每年的比赛非常多,像国赛、美赛、深…

直流电机的基本原理与结构

一些基本定理 磁感应强度(又称磁通密度)B —— 表征磁场强弱及方向的物理量。单位:T 右手定则:伸开右手,使拇指与其余四个手指垂直,并且都与手掌在同一平面内;让磁感线从手心进入,…

软件设计师基础知识难点总结

软件设计师基础知识难点 I/O设备管理软件一般分为4个层次,如下图所示。 用户进程与设备无关的系统软件设备驱动程序中断处理程序硬件 直接查询控制 分为有无条件传送和程序查询方式,都需要通过CPU执行程序来查询外设的状态,判断外设是否准备好…

牛客热题:有效括号

📟作者主页:慢热的陕西人 🌴专栏链接:力扣刷题日记 📣欢迎各位大佬👍点赞🔥关注🚓收藏,🍉留言 文章目录 牛客热题:有效括号题目链接方法一&#x…

数据结构--二叉搜索树

目录 二叉搜索树的概念 二叉树的实现 结点类 函数接口总览 实现二叉树 二叉搜索树的应用 K模型 KV模型 二叉搜索树的性能分析 二叉搜索树的概念 二叉搜索树(Binary Search Tree,简称BST)是一种特殊的二叉树,其具有以下几…

CSP俄罗斯方块(简单易懂)

开始将题目理解成了&#xff0c;开始的列应该是从输入图案的最左端开始计算&#xff0c;将前面所有的空列都删掉&#xff0c;代码如下&#xff1a; #include<bits/stdc.h> using namespace std; const int N 1e410; const int M 1e510; int a[20][20]; int b[5][5];int…

【yolov10】使用自己的数据集训练目标检测模型

【yolov10】使用自己的数据集训练目标检测模型 一、anaconda安装二、环境配置三、数据集制作1、labelimg的安装2、使用labelimg 四、正片1、下载yolov10源码2、数据集目录3、训练4、推理 一、anaconda安装 直接参考前一篇博客&#xff1a; https://blog.csdn.net/m0_71523511/…

八国多语言微盘微交易所系统源码 单控点控 K线完好

安装环境linux NGMySQL5.6PHP7.2&#xff08;函数全删&#xff09;pm2管理器&#xff08;node版本选择v12.20.0&#xff09; config/ database.php 修改数据库链接 设置运行目录 public 伪静态thinkphp

【图解IO与Netty系列】IO的同步与异步、阻塞与非阻塞,Linux五种IO模型

IO的同步与异步、阻塞与非阻塞&#xff0c;Linux五种IO模型 IO的同步与异步&#xff0c;阻塞与非阻塞阻塞IO与非阻塞IO同步IO与异步IO Linux五种IO模型BIONIOIO多路复用信号驱动IOAIO IO的同步与异步&#xff0c;阻塞与非阻塞 我们有时会看到类似于同步阻塞式IO、同步非阻塞式…