理解IO多路复用
I/O 多路复用是什么?
I/O 多路复用是用户程序通过复用一个线程来服务多个 I/O 事件的机制,我们也可以将他说成是一个线程服务多个文件描述符 fd,而 I/O 多路复用是在操作系统层面实现提供的,举个例子:Linux 平台下常见的 I/O 多路复用有:select、poll、epoll
刚刚提到文件描述符 fd,那 fd 到底是什么?有什么作用?
- fd 是文件描述符,用来表示一个文件,我们可以通过 fd 找到对应的文件并对他进行读写操作
- 可以说 fd 是一个索引值,能帮助我们索引到对应的 socket 文件或是已经打开的磁盘文件
那 socket 又是什么?
- socket 文件代表操作系统内核中的一段 buffer,数据从客户端传输过来后,通过网络协议栈的处理,socket 文件中保存的就是客户端传来的数据,读取 socket 文件就能获取到客户端相关的数据,形象的说,socket 就像是一个能够进行双向数据传输的管道
- 举个例子,当客户端和服务端建立通信,双方都存在一个 socket 文件,socket 建立内核 buffer 和用户程序的通道完成数据的传输
那数据到达我们的服务器,被用户程序读取到,中间的过程具体是什么样的?
看图:

- 数据在客户端进行层层包装之后,传输到我们的服务器,网卡通过 DMA 技术将收到的 frame 写到操作系统的内核,接着触发 CPU 中断,让操作系统不断从 buffer 中取出数据交给协议栈处理,数据在经过协议栈处理后进入 socket 文件,所以 socket 文件中就存在了客户端相关的数据,我们就可以对这些数据进行读写操作了
什么是 DMA 技术?
- DMA(Direct Memory Access)用于在外设与存储器之间以及存储器与存储器之间提供高速数据传输,可以在无需任何 CPU 操作的情况下通过 DMA 快速移动数据,这样节省的 CPU 资源可供其它操作使用。
什么是 frame?
- 一个 http 报文最终会传输到数据链路层,而链路层(以太网)的最基本单位是 frame,也叫做以太帧
问题来了,那为什么需要 I/O 多路复用?
- 刚刚我们聊到,客户端的数据传输过来,进入了 socket 文件中,当他们发生事件的时候,用户程序需要创建线程进行处理
- 一般 fd 对应两种事件
- 是否可以写(缓冲区满了,可能写不下,注册事件,等到可以写了,通知我)
- 是否可以读(缓冲区有数据的时候,就可以读了)
- 而网卡能够知道 fd 是否有时间发生,并通知操作系统,但用户程序不知道
- 一般 fd 对应两种事件
- I/O 多路复用就是解决这一个问题,让线程快速得知 fd 是否有事件发生(是否可以读,是否可以写)
- 一个线程能并发的服务多个 I/O 事件,这就是 I/O 多路复用的含义
总结:如何理解 I/O 多路复用
- 如果不使用 I/O 多路复用,在并发处理多个客户端的 I/O 事件的的场景下,服务端需要通过创建子进程或者线程的方式,给每一个连接的 I/O 事件分配一个线程来处理,随着客户端越来越多,服务端需要创建更多的线程,系统的开销太大,效率太低
- 我们需要一种机制,让一个线程能并发的服务多个 I/O 事件,这就是 I/O 多路复用的含义
- 所以操作系统设立了多种 I/O 多路复用的机制来解决这个问题,线程可以通过 select、poll、epoll 这类 I/O 多路复用系统调用接口从内核中通过网卡获取有事件发生的 socket 集合,然后就可以通过遍历这个集合,对每一个 I/O 事件进行处理,这样就实现了一个线程并发的处理多个 I/O 事件,大大提高了效率
这就是为什么我们需要 I/O 多路复用的技术
理解IO多路复用的更多相关文章
- Python:通过一个小案例深入理解IO多路复用
通过一个小案例深入理解IO多路复用 假如我们现在有这样一个普通的需求,写一个简单的爬虫来爬取校花网的主页 import requests import time start = time.time() ...
- 一文彻底理解IO多路复用
在讲解IO多路复用之前,我们需要预习一下文件以及文件描述符. 什么是文件 程序员使用I/O最终都逃不过文件. 因为这篇同属于高性能.高并发系列,讲到高性能.高并发就离不开Linux/Unix,因此这里 ...
- 概念理解-IO多路复用
epoll 是 Linux 内核为处理大批量文件描述符而作了改进的 poll,是 Linux 下多路复用 IO接口 select/poll 的增强版本 在 linux 的网络编程中,很长时间都在使用 ...
- 最快理解 - IO多路复用:select / poll / epoll 的区别.
目录 第一个解决方案(多线程) 第二个解决方案(select) 第三个解决方案(poll) 最终解决方案(epoll) 客栈遇到的问题 从开始学习编程后,我就想开一个 Hello World 餐厅,由 ...
- IO多路复用,同步,异步,阻塞和非阻塞 区别
一.什么是socket?什么是I/O操作? 我们都知道unix(like)世界里,一切皆文件,而文件是什么呢?文件就是一串二进制流而已,不管socket,还是FIFO.管道.终端,对我们来说,一切都是 ...
- 趣谈IO多路复用的本质
在<轻松搞懂5种IO模型>中,我发起了一个投票. 答案是[同步IO多路复用].目前,60%的朋友答对了.原因这里解释一下. 同步和异步的概念区别 同步:线程自己去获取结果.(一个线程) 异 ...
- IO多路复用之select,poll,epoll个人理解
在看这三个东西之前,先从宏观的角度去看一下,他们的上一个范畴(阻塞IO和非阻塞IO和IO多路复用) 阻塞IO:套接口阻塞(connect的过程是阻塞的).套接口都是阻塞的. 应用程序进程-----re ...
- IO多路复用的理解
最近看了<后台开发核心技术与应用实践>有关select.poll和epoll部分以及相关的一些博客,学习了这三个函数的使用方法和区别,写一个易理解的总结. IO多路复用 之前程序中使用的I ...
- 深入理解计算机操作系统——12章:多进程,IO多路复用
三种并行的应用程序: 1. 基于进程的并发编程: 2. 基于IO多路复用的并发: 3. 基于线程的并发编程: 12.1 基于进程的并发编程 进程的优劣: (1)进程间共享文件表,但不共享用户地址空间, ...
- IO多路复用?我所理解的IO模式
1:IO的过程 当我们调用系统函数read时,一般会经历两个阶段: 1:等待数据准备(waiting for the data be ready) 2:将数组从内核拷贝到进程(从内核态到用户态)(co ...
随机推荐
- [项目自荐] 交叉编译njs并使用Nginx搭建自由的个人网盘:vList5
这个博客好久没有打理了,最近才想起来 这篇文章是以下 5 篇文章的组合,希望这个免费的项目能实现他的初衷吧 vList5:部署指南 vList5.3 全面加密,从我做起 njs 从入门(交叉编译)到入 ...
- SQL Server 查询分析及优化方法
一.影响速度的因素 没有索引或者没有用到索引(这是查询慢最常见的问题,是程序设计的缺陷) I/O吞吐量小,形成了瓶颈效应 没有创建计算列导致查询不优化 内存不足 网络速度慢 查询出的数据量过大(可以采 ...
- Kubernetes 部署Dashboard UI
实践环境 CentOS-7-x86_64-DVD-1810 Docker 19.03.9 Kubernetes version: v1.20.5 发布Dashboard 可以通过运行以下命令部署Das ...
- CF941
A link 其实,只要有第一次,那么下次随意找一个队列里有的数加\(k-1\)个进去,加上队列里那一个删掉\(k\)个,到最后一次肯定是剩\(k-1\)个. 没有第一次,就是\(n\). 点击查看代 ...
- CRC 循环冗余效验
CRC循环冗余效验 利用多项式 x6 + x4 + x3,实际为使用模2除法来做的加密 常用crc多项式有 名称 生成多项式 数值式 简记式 标准引用 CRC-4 x4+x+1 0x1'3 0x3 I ...
- Python获取指定网段正在使用的IP
Python获取指定网段正在使用的IP #!/usr/bin/env python # -*- coding: utf-8 -*- ''''' 使用方法样例 python test20.py 192. ...
- [rCore学习笔记 020]第二章作业
写在前面 本随笔是非常菜的菜鸡写的.如有问题请及时提出. 可以联系:1160712160@qq.com GitHhub:https://github.com/WindDevil (目前啥也没有 编程题 ...
- 【Git】下载安装(Linux)
安装CentOS8貌似有自带Git 可以先查看一下有没有 git --version 有或者没有都行,有的话安装就当是更新 没有就装,yum提供了安装,我们不需要自己压缩包安装了 yum instal ...
- 【Vue】08 Webpack Part4 使用Vue
新建一个目录创建Vue项目: cd .. mkdir webpack-vue cd webpack-vue 安装Vue cnpm install vue 保持之前的目录结构: 在Main.js中引用V ...
- java主线程等待多个子线程中任意一个有结果后,主线程继续执行
1.背景 2.代码 package com.qianxingniwo.ls; import org.junit.Test; import java.util.concurrent.atomic.Ato ...