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

五种IO模型

用户空间与内核空间

操作系统把内存空间划分成了两个部分:内核空间和用户空间。
为了保护内核空间的安全,操作系统一般都限制用户进程直接操作内核。

所以,当我们使用TCP发送数据的时候,需要先将数据从用户空间拷贝到内核空间,再由内核空间拷贝到网卡;
当我们使用TCP读取数据的时候,数据需要先从网卡拷贝到内核空间,再从内核空间拷贝到用户空间供用户进程使用。

在这里插入图片描述

内核空间与网卡的数据拷贝使用DMA技术,不需要CPU参与。

缓存IO

缓存I/O又被称作标准I/O,大多数文件系统的默认I/O操作都是缓存I/O。 在Linux的缓存I/O机制中,
数据先从磁盘复制到内核空间的缓冲区(PageCache), 然后从内核空间缓冲区复制到应用程序的地址空间。

读操作 操作系统检查内核的缓冲区有没有需要的数据,如果已经缓存了,那么就直接从缓存中返回;
否则从磁盘中读取,然后缓存在操作系统的缓存中。

写操作 将数据从用户空间复制到内核空间的缓存区。这时对用户程序来说写操作就已经完成,
至于什么时候再写到磁盘中由操作系统决定,除非显示地调用了sync同步命令。

缓存I/O的优点 首先,在一定程度上分离了内核空间和用户空间,保护系统本身的运行安全;
其次,可以减少读盘的次数,从而提高性能。

缓存I/O的缺点 在缓存 I/O 机制中,DMA方式可以将数据直接从磁盘读到页缓存中,
或者将数据从页缓存直接写回到磁盘上,而不能直接在应用程序地址空间和磁盘之间进行数据传输,
这样,数据在传输过程中需要在应用程序地址空间(用户空间)和缓存(内核空间)之间进行多次数据拷贝操作,
这些数据拷贝操作所带来的CPU以及内存开销是非常大的。

IO模式

对于一次IO访问(以read举例),数据会先被拷贝到操作系统内核的缓冲区中,
然后才会从操作系统内核的缓冲区拷贝到应用程序的地址空间(用户空间)。

所以说,当一个read操作发生时,它会经历两个阶段:

1.内核空间准备好数据

2.将数据从内核空间拷贝到用户空间

因为这两个阶段,Linux系统产生了下面五种IO模型

阻塞型IO

当用户进程发起read操作,一直阻塞直到数据拷贝到用户空间为止才返回。

阻塞型IO第一阶段和第二阶段都阻塞。

在这里插入图片描述

非阻塞型IO

非阻塞型IO,用户进程不断询问内核,数据准备好了吗?
一直重试,直到内核说数据准备好了,然后把数据从内核空间拷贝到用户空间,返回成功,开始处理数据。

非阻塞型IO第一阶段不阻塞,第二阶段阻塞。

在这里插入图片描述

IO多路复用

IO多路复用,会将多个Socket注册到一个选择器(Selector)。
相当于可以使用一个线程来管理多个Socket连接。在最初的阻塞型IO,每来一个新的连接都需要分配一个线程来处理。

IO多路复用有三种模式:select、poll、epoll。当用户调用select/poll/epoll,会阻塞当前进程,
内核会不断的轮询注册到选择器(Selector)上的Socket,当任何一个Socket的数据准备好了,就会结束阻塞。
这个时候用户进程再调用read操作,将数据从内核空间拷贝到用户空间。

IO多路复用,第一阶段会阻塞在Selector上,第二阶段拷贝数据也会阻塞。

在这里插入图片描述

信号驱动IO

信号驱动IO,用户进程发起read请求之前先注册一个信号给内核说明自己需要什么数据,这个注册请求立即返回。
等内核数据准备好了,主动通知用户进程,用户进程再去请求读取数据,此时,需要等待数据从内核空间拷贝到用户空间再返回。

信号驱动,第一阶段不阻塞,第二阶段阻塞。

在这里插入图片描述

异步IO

异步IO,用户进程发起read请求后立马返回,当数据完全拷贝到用户空间后通知用户直接使用数据。

异步IO,两个阶段都不阻塞。

在这里插入图片描述

阻塞与非阻塞

阻塞:是指调用结果返回之前,当前线程会被挂起,直到调用结果返回。

比如Socket编程中,使用java.io.InputStream#read(byte[])方法读取数据,
如果没有可读数据,就会一直阻塞当前线程,直到有可读数据才会返回。

非阻塞:不能立即得到结果之前,当前线程不被挂起,而是可以继续做其它的事。

同步与异步

同步:调用者会被阻塞直到IO操作完成,调用的结果随着请求的结束而返回。。

异步:调用者不会被阻塞,调用的结果不随着请求的结束而返回,而是通过通知或回调函数的形式返回。

阻塞/非阻塞,更关心的是当前线程是不是被挂起。

同步/异步,更关心的是调用结果是不是随着请求结束而返回。

阻塞是指整个IO过程中是否有阻塞,所以,
阻塞型IO、非阻塞型、IO多路复用、信号驱动IO都是同步IO,只有最后一种才是异步IO。


http://www.kler.cn/a/760.html

相关文章:

  • TF-IDF(Term Frequency-Inverse Document Frequency)详解:原理和python实现(中英双语)
  • OCR实践-Table-Transformer
  • Vue3入门(9)
  • win版ffmpeg的安装和操作
  • js版本之ES6特性简述【Proxy、Reflect、Iterator、Generator】(五)
  • RestTemplate关于https的使用详解
  • k8s快速入门
  • 响应式编程详解,带你熟悉Reactor响应式编程
  • 操作系统之进程的初步认识(1)
  • Vulnhub靶场----10、LazySysadmin
  • 文心一言发布我怎么看?
  • 18、江科大stm32视频学习笔记——USART串口发送串口发送和接收
  • 【2023-3-6】1. Nginx介绍及安装
  • Centos系统下载
  • 图解redis之链表的实现
  • 深度学习必备知识——模型数据集Yolo与Voc格式文件相互转化
  • Linux驱动开发
  • 【动态规划】不同路径,编辑距离题解及代码实现
  • Linux -- 磁盘存储管理 分区工具 parted
  • 硬刚ChatGPT!文心一言能否为百度止颓?
  • 百度发布文心一言,我想说几句
  • 【申请加入New Bing遇到的问题:当前无法使用此页面,cn.bing.com 重定向次数过多】
  • 运筹系列67:大规模TSP问题的EAX遗传算法
  • python自动化办公(一)
  • Python语言在地球科学交叉领域中的实践技术融合应用
  • 【C语言】—— qsort()函数的使用