当前位置: 首页 > news >正文

IO多路复用--[select | poll | epoll | Reactor]

因为在简历上写了netty的项目,因此还是将网络底层的那点东西搞清楚。
首先希望明确的是,BIO、NIO、IO多路复用这是不同的东西, 我会在本文中详细讲出来。
本文参考资料:
JAVA IO模型
IO多路复用 select poll epoll介绍
从BIO到epoll
UNIX网络编程 推荐看一下

1. BIO与NIO

在一次输入操作中,有两个不同的阶段:

  1. 等待内核态的数据准备完毕。(比如说输入操作是读取磁盘,那么我们需要等待磁盘寻址、加载到内存,这些过程就是数据准备阶段)
  2. 将内核态的数据拷贝到用户态。(在数据准备完毕后,为了用户态的程序使用,需要将内核态的数据拷贝给用户态,这个阶段用时很小)。
BIO的读取流程

在这里插入图片描述
BIO的读取流程很简单,对于每一个进行读取操作的线程,线程从接受这个读取请求到最终将数据返回用户态的整个过程都是阻塞的。举个小例子,如果使用BIO读取磁盘文件,那么读取线程在 {等待磁盘寻址、页加载等数据准备流程,最终将数据从内核态拷贝到用户态} 这整个流程中都是被阻塞的。

NIO的读取流程

在这里插入图片描述
在BIO中,阻塞操作极大地影响了线程的利用率:线程在准备数据阶段无事可做,但是却不能抽身去处理其他的IO操作。因此NIO就是解决这个事情,NIO在接收IO请求时,并不会在数据处理阶段阻塞住,而是不断地询问这个文件描述符:你的数据准备好了吗。如果准备好了的话那么就将数据从内核态拷贝到用户态,然后返回。

可以看出,NIO并不是在全过程都是非阻塞的,而是在数据准备阶段非阻塞,在数据拷贝阶段阻塞。但是由于数据拷贝阶段时间很短,因此几乎相当于非阻塞。

上面这么说有点抽象,我们来聊一聊怎么使用NIO去进行读取。

  • 假设说我们现在有100个客户端连接,在linux中一切即文件,因此我们具有100个文件描述符fd
  • 我们在一个while循环中不断地遍历这100个fd,去查看其数据是否准备好,一旦准备好了,那么就进行数据拷贝阶段,这个fd的IO过程随之结束。如果没有准备好,我们继续对其遍历。
  • 写成代码格式就是这样:
// 具有一系列文件描述符
fds = [fd1, fd2...]

while(true){
	for (fd in fds){
		// 判断fd中的数据是否准备完毕
		// 这个过程会涉及系统调用,因为文件描述符是内核态的东西
		boolean ready = is_ready(fd)
		if (ready){
			// 进行数据拷贝等一系列操作
		}
	}
}

2. IO多路复用

通过上面的BIO代码我们可以看出,遍历文件描述符这个操作是用户态完成的,在每一次循环过程中,我们都需要对每个fd进行一次系统调用,当我们有100个fd时,每次遍历文件描述符就需要100次系统调用,在用户态到内核态进行切换是很耗费资源的。

那么用户态能解决这个事情吗?肯定是不行的,因此从上个实际80年代开始,unix就开始逐渐提供select, poll, epoll等机制,在内核态去遍历文件描述符。这三个机制实现细节有些差异,但是整体流程都是:用户态接受到文件描述符,将文件描述符的列表fds交给内核态,进行系统调用,内核态完成文件描述符的遍历,将数据准备就绪的文件描述符返回给用户态。因此,一次遍历从之前的100次系统调用就减少为1次系统调用。

因此IO多路复用,复用的是什么?复用的实际上是系统调用,从之前的一次系统调用判断一个文件描述符,变成了一次系统调用判断整个文件描述符列表。

Reactor

这部分内容较多,详见下一篇文章

相关文章:

  • java面试八股文之------Java并发夺命23问
  • 23.3.14打卡 2022年江西省大学生程序设计竞赛(正式赛)ABL
  • FPGA实现CSI-2 解码MIPI视频 2line 720P分辨率 OV5647采集 提供工程源码和技术支持
  • 改进YOLO系列 | CVPR2023最新Backbone | FasterNet 远超 ShuffleNet、MobileNet、MobileViT 等模型
  • 蓝桥杯刷题冲刺 | 倒计时28天
  • 改进 YOLO V5 的密集行人检测算法研究(论文研读)——目标检测
  • GPT4来了,多模态模型上线
  • 【C/C++】必知必会知识点大总结
  • css 画图之质感盒子
  • C/C++网络编程笔记Socket
  • 学习 Python 之 Pygame 开发魂斗罗(十一)
  • Spring整体架构包含哪些组件?
  • 「SAP ABAP」OPEN SQL的DML语句你了解多少 (附超详细案例讲解)
  • 比较cpp-httplib,Drogon和Mongoose三个方案
  • Java【lambda表达式】语法及使用方式介绍
  • 【面试系列】之二:关于js原型
  • 【许晓笛】 EOS 智能合约案例解析(3)
  • DOM的那些事
  • exif信息对照
  • JSONP原理
  • Linux链接文件
  • Mac 鼠须管 Rime 输入法 安装五笔输入法 教程
  • magento2项目上线注意事项
  • PHP 使用 Swoole - TaskWorker 实现异步操作 Mysql
  • SpiderData 2019年2月25日 DApp数据排行榜
  • 阿里云购买磁盘后挂载
  • 初识MongoDB分片
  • 看域名解析域名安全对SEO的影响
  • 使用 Docker 部署 Spring Boot项目
  • 使用API自动生成工具优化前端工作流
  • 微信如何实现自动跳转到用其他浏览器打开指定页面下载APP
  • 智能合约开发环境搭建及Hello World合约
  • Unity3D - 异步加载游戏场景与异步加载游戏资源进度条 ...
  • 进程与线程(三)——进程/线程间通信
  • ​ArcGIS Pro 如何批量删除字段
  • ​软考-高级-系统架构设计师教程(清华第2版)【第12章 信息系统架构设计理论与实践(P420~465)-思维导图】​
  • #162 (Div. 2)
  • #每天一道面试题# 什么是MySQL的回表查询
  • (09)Hive——CTE 公共表达式
  • (10)ATF MMU转换表
  • (11)工业界推荐系统-小红书推荐场景及内部实践【粗排三塔模型】
  • (6)【Python/机器学习/深度学习】Machine-Learning模型与算法应用—使用Adaboost建模及工作环境下的数据分析整理
  • (C)一些题4
  • (Java)【深基9.例1】选举学生会
  • (Redis使用系列) SpringBoot 中对应2.0.x版本的Redis配置 一
  • (ResultSet.TYPE_SCROLL_INSENSITIVE,ResultSet.CONCUR_READ_ONLY)讲解
  • (ZT)薛涌:谈贫说富
  • (八)Docker网络跨主机通讯vxlan和vlan
  • (二)Pytorch快速搭建神经网络模型实现气温预测回归(代码+详细注解)
  • (附源码)ssm失物招领系统 毕业设计 182317
  • (实战篇)如何缓存数据
  • (淘宝无限适配)手机端rem布局详解(转载非原创)
  • (推荐)叮当——中文语音对话机器人
  • (详细版)Vary: Scaling up the Vision Vocabulary for Large Vision-Language Models
  • (原創) 博客園正式支援VHDL語法著色功能 (SOC) (VHDL)