NIO原理浅析(二)

news2025/4/6 18:38:27

IO分类

阻塞和非阻塞

阻塞IO:用户空间引发内核空间的系统调用,需要内核IO操作彻底完成之后,返回值才会返回到用户空间,执行用户的操作。阻塞指的用户空间程序的执行状态,用户空间程序需要等到IO操作彻底执行完毕。java中,默认创建的socket是阻塞的。

非阻塞IO:用户空间引发内核空间的系统调用,不需要等待内核IO操作彻底完成,内核立即给用户返回一个返回值。用户空间程序继续执行用户的操作,处于非阻塞的状态。java中,设置非阻塞的IO,以socket为例,见如下所示的代码:

serverChannel = ServerSocketChannel.open()
serverChannel.configureBlocking(false)

有兴趣,也可以参考java中关于Socket这个类的文档
在这里插入图片描述

同步和异步

同步IO:用户空间和内核空间的调用发起方式。同步IO是指用户空间的线程是主动发起IO请求的一方,内核空间是被动接受方。

异步IO:用户空间和内核空间的调用发起方式。异步IO是指用户空间的线程是被动接受方,但是内核空间里面的kernel是主动发起IO请求的一方。
在这里插入图片描述

四种常见的IO模型

服务器端的编程需要构造高性能的IO模型,常见的IO模型有四类:

在这里插入图片描述

同步阻塞IO(Blocking IO):

结合上面的描述,同步阻塞IO指的是用户空间主动发起的调用,然后需要等待内核空间将IO操作彻底完成之后才会返回用户空间,这期间,用户空间线程将会处于阻塞状态。
在这里插入图片描述

BIO优点: 程序简单,在阻塞等待数据的期间,用户挂起线程,用户线程基本不会占用CPU资源。

BIO缺点:每个请求可能会配置一套独立的线程,当并发量很高的场景下,内存和线程切换的成本很高。

应用举例:在Java中使用线程池的方式去连接数据库,就是使用的同步阻塞IO模型。

同步非阻塞IO(Non-blocking IO):

如果是socket被设置为non-blocking,NIO模型如果出现了系统调用,会出现以下两种情况:

(1)当内核缓存区里面没有数据,那么当用户空间发起的系统调用时,会立即返回一个失败的信息

(2)当内核缓存区里面有数据,那么当用户空间发起的系统调用时,会进入到阻塞状态,将内核缓存区里面的数据复制到用户缓冲区。直到数据返回成功,才会解除阻塞的状态。

在这里插入图片描述

NIO的优点:每次发起IO系统调用,线程在内核等待缓冲区数据的时候,会立即返回值,不会阻塞。实时性比较好。

NIO的缺点:需要不断地轮询发起系统调用,这样会占用大量的CPU时间,资源利用率很低。

IO多路复用(IO Multiplexing)

首先从字面意思来理解多路复用:

  • 多路: 多个socket网络连接

  • 复用:复用一个线程,使用一个线程来检查多个文件套接字(又称文件句柄)的就绪状态

IO多路复用是一种同步IO模型,实现用一个线程监视多个文件句柄,一旦有文件句柄准备就绪,就可以通知应用程序进行相应的读写操作。没有文件句柄就绪,就会阻塞应用程序,然后交出CPU的时间片。

通过对之前两种IO模型的总结,我们可以发现:

针对高并发的场景,同步阻塞模型的缺点是需要做频繁的内存和线程的切换,效率很低。同步非阻塞的缺点是要在用户程序空间轮询的发起系统调用,这导致内核态和用户态的频繁切换,也会消耗大量的资源。

IO多路复用则可以避免内核态和用户态的频繁切换,因为IO多路复用模型将轮询套接字(又称为文件句柄)的动作,直接放在了内核态进行,这样避免了内核态和用户态的频繁切换

举例说明

我们以基础的socket模型为例,展现IO多路复用的机制:

下面是基础的socket模型伪码:

listenSocket = socket(); //系统调用socket()函数,调用创建一个主动socket
bind(listenSocket); //给主动socket绑定地址和端口
listen(listenSocket); //将默认的主动socket转换成服务器使用的被动socket(也叫监听socket)
while(true) { //循环监听客户端的连接请求
  connectSocket = accept(listenSocket); //接受客户端连接,获取已连接socket
  recv(connSocket); //从客户端读取数据,只能同时处理一个客户端
  send(connSocket); //给客户端返回数据,只能同时处理一个客户端
}

网络通信的流程如下图所示:
在这里插入图片描述

上图所示的socket网络通信,是典型的同步阻塞模型,当有大量客户端连接时,这种模型的处理性能比较差。使用IO多路复用可以解决这种困境。


linux中,操作系统提供了select、poll和epoll三种多路复用机制。

select机制

四个问题

1、IO多路复用可以最多监听多少个socket?

2、IO多路复用可以监听socket里面的哪些事件?

3、IO多路复用如何感知已经就绪的文件描述符fd?

4、IO多路复用如何实现网络通信?

首先在linux平台上查看一下select函数定义,可以参考一下文章1Linux内核select源码剖析 、文章2Linux select源码分析。

/**
* 参数说明
* 监听的文件描述符数量 __nfds
* 被监听描述符的三个集合*__readfds, *__writefds 和 *__exceptfds
* 监听时阻塞等待的超时时长*__timeout
* 返回值:返回一个socket对应的文件描述符
*/
int select(int __nfds, fd_set * __readfds, 
           fd_set * __writefds, fd_set * __exceptfds, 
           struct timeval * __timeout)

select函数监听的文件描述符被分成三类,分别是__readfds, __writefds 和 __exceptfds,当用户调用select时,假设当前监控的是___readfds集合,select操作会将需要监控___readfds集合从用户空间拷贝到内核空间,随后在内核空间一直遍历自身的skb(SocketBuffer),检查每个skb的poll逻辑,已确定socket是否存在可读事件。若没有socket可读,则会进入到睡眠状态。当发现有sokcet可读,则会唤醒用户空间的程序,然后在用户态去遍历监控的集合,并读取数据。

在这里插入图片描述

select 多路复用方法存在的缺陷:

1、调用select需要将套接字列表从用户态复制到内核态,对于多并发场景,资源消耗量比较大。

2、能监听的端口号的数量有限制,FD_SETSIZE,32位机器限制1024个套接字,64位机器限制2048个套接字。

3、被监控的fdlist列表,如果有一个套接字数据可读,业务就需要遍历一遍用户态的fdlist列表,时间复杂度O(n)。

poll

相较于select,poll优化了select的缺陷二,使用的是pollfd结构,而不是fd_set结构,突破了1024的限制,但是poll没有解决缺陷1和缺陷3,仍然需要导致用户态到内核态的资源消耗过大的问题。

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

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

相关文章

《关键跨越:从业务高手到优秀主管》:最大化团队产出

作者:北森人才管理研究院 阅读时长:6小时21分钟 评分:5星 失控最鲜明的特征之一是管理者工作的时间越来越长,但结果越来越糟。很多新手管理者看到下属无法完成任务,或者担心出错,对下属不放心,出…

Linux学习之RAID删除

参考《Linux软件raid删除》 我部署 RAID的步骤在《Linux学习之RAID》 sudo umount /dev/md0先进行卸载。 sudo mdadm -S /dev/md0停止/dev/md0。 sudo mdadm -A -s /dev/md0可以重新开始/dev/md0,这里只是拓展一下。 sudo mdadm -S /dev/md0停止/dev/md0。 s…

Cesium 加载 geojson 文件并对文件中的属性值进行颜色设置

文章目录 需求分析解决 需求 Cesium 加载 geojson 文件并对文件中的属性值进行颜色设置 分析 在搜寻多种解决方案后,最后总结出 自己的解决方案 方案一,没看懂 var geojsonOptions {clampToGround : true //使数据贴地};var entities;promise Cesium…

详解产品项目管理软件:介绍与比较

产品项目管理是指通过有效的规划、组织和控制来管理产品开发过程的一系列活动。它涵盖了需求分析、产品设计、开发、测试以及上市等不同阶段,并需要协调多个团队成员的工作。通过产品项目管理,团队可以更好地把握产品的战略目标、工作进度和资源分配&…

Oracle-day6:over()函数

目录 一、over()开窗函数 二、无参over()的使用 三、over(partition by 列名) 四、over(order by 列名 asc/desc) 五、over(partition by 列名 order by 列名 asc|desc) 六、练习(笔试) 一、over()开窗函数 拓展:数据库的版本 oracle:8i 9i 10g …

ICCV 2023 | 小鹏汽车纽约石溪:局部上下文感知主动域自适应LADA

摘要 主动域自适应(ADA)通过查询少量选定的目标域样本的标签,以帮助模型从源域迁移到目标域。查询数据的局部上下文信息非常重要,特别是在域间差异较大的情况下,然而现有的ADA方法尚未充分探索这一点。在本文中&#…

六、事务-4.并发事务问题

一、脏读 事务A执行3个操作,第1个操作执行select语句,第2个操作执行update语句。 注意:事务没有执行完成的时候,事务是没有提交的。只有事务的3个操作完成之后,事务才会提交。 但事务A中第2个操作,会把表…

改进YOLOv8系列:原创改进创新点 SIoU-NMS,EIoU-NMS,DIoU-NMS,CIoU-NMS,GIoU-NMS改进

💡该教程为属于《芒果书》📚系列,包含大量的原创首发改进方式, 所有文章都是全网首发原创改进内容🚀 💡本篇文章为YOLOv8独家原创改进:原创改进创新点 DIoU-NMS,SIoU-NMS,EIoU-NMS,CIoU-NMS,GIoU-NMS改进。 💡对自己数据集改进有效的话,可以直接当做自己的原创改…

机器学习笔记之最优化理论与方法(二)凸集的简单认识(上)

机器学习笔记之最优化理论与方法——凸集的简单认识[上] 引言凸优化问题与凸集合凸函数的关系凸优化问题简单示例凸集的简单示例 基本定义:凸集关于凸集性质的等价条件,凸组合,凸包常见凸集 引言 本节将介绍关于凸集的基本信息,包…

【Java】基础入门 (十六)--- 异常

1.异常 1.1 异常概述 异常是指程序在运行过程中出现的非正常的情况,如用户输入错误、除数为零、文件不存在、数组下标越界等。由于异常情况再程序运行过程中是难以避免的,一个良好的应用程序除了满足基本功能要求外,还应具备预见并处理可能发…

青翼科技基于VITA57.1的16路数据收发处理平台产品手册

FMC211是一款基于VITA57.1标准规范的实现16路LVDS数据采集、1路光纤数据收发处理FMC子卡模块。 该板卡支持2路CVBS(复合视频)视频输入,能够自动检测标准的模拟基带电视信号,并将其转变为8位ITU-R.656接口信号或者4:2:2分量视频信…

Qt网络通信——获取本机网络信息

查询一个主机的MAC地址或者IP地址是网络应用中常用到的功能&#xff0c;Qt提供了QHostInfo和QNetworkInterface 类可以用于此类信息的查询 1.QHostInfo 类&#xff08;显示和查找本地的信息&#xff09;是的主要函数 类别 函数原型作用公共函数QList <QHostAdress> addr…

读<一例 Go 编译器代码优化 bug 定位和修复解析>

看到一例 Go 编译器代码优化 bug 定位和修复解析[1]这样一篇文章,感觉有些意思. 在此复现和记录 在Go 1.16版本下,是没有这个bug[2]的(已修复). 参照gvm:灵活的Go版本管理工具[3] 将Go版本切至有问题的1.13.5(或1.14.6) ➜ go versiongo version go1.13.5 darwin/amd64 packag…

Node常用内置模块之url模块和querystring模块

1、URL类 url模块在v16的nodejs中已经明确被废弃&#xff0c;在将来的升级node中&#xff0c;可能被不支持。 官网建议在废弃url、querystring模块后&#xff0c;采用URL类去替代。 图示 URL 各部分 旧版的url模块 作用&#xff1a;url 模块是用于处理和解析 URL 的模块&…

Unity ShaderGraph教程——基础shader

1.基本贴图shader&#xff1a; 基础贴图实现&#xff1a;主贴图、自发光贴图、光滑度贴图、自发光贴图&#xff08;自发光还加入了颜色影响和按 钮开关&#xff09;. 步骤&#xff1a;最左侧操作组——新建texture2D——新建sample texture 2D承…

Linux上部署zentao禅道18.6版本

1. cd /opt 2. 下载 ZenTaoPMS-18.6-zbox_amd64.tar.gz wget https://dl.cnezsoft.com/zentao/18.6/ZenTaoPMS-18.6-zbox_amd64.tar.gz 3. 解压 tar -zxvf ZenTaoPMS-18.6-zbox_amd64.tar.gz 4. 解压成功, 可以看到多了个zbox文件 5. cd zbox/ 进入该目录 6. 修改apache默认…

乙酰基六肽-18——刺激脂肪合成,增加指定部位脂肪,塑造完美曲线

简介 乙酰六肽-18&#xff08;丰胸肽&#xff09;为一种乙酰化的六肽&#xff0c;可显著刺激使用部位脂肪合成&#xff0c;增大胸部或脸颊的体积&#xff0c;塑造完美身材。 INCI 名称 乙酰六肽-18 分子式 C30H54N9O10 分子量 700.32 CAS号 1400634-44-7…

WPF_布局基础

布局容器 Grid 定义由列和行组成的灵活的网格区域。 行 <Grid.RowDefinitions><RowDefinition/><RowDefinition/></Grid.RowDefinitions> 列 <Grid.ColumnDefinitions><ColumnDefinition/><ColumnDefinition/></Grid.ColumnDe…

免费开源MES系统|自动排产管理

万界星空科技免费MES系统助力企业实现生产排程自动化&#xff0c;降低人力成本。生产计划排产管理是指制定一个可行的生产计划并按照该计划安排生产资源和制造活动的过程。 它是制造企业管理中的一个关键过程&#xff0c;涉及到计划制定、资源管理、物料采购、工厂布局、生产调…

手搓的一款基于sql脚本的数据初始化组件

产口孵化新项目时&#xff0c;表中需要提前预置部份数据。如字典&#xff0c;角色、菜单、配置等。以达到快速布署的目的。这部份数据会随着某些因素的影响。如地区变化、系统定制方面。无法使用统一的一份sql。旧方案是在代码里面动态的作insert操作。在项目启动的时候初始化这…