操作系统的几种IO方式

目前IO模型主要经历了以下五种:
1)阻塞IO
2)非阻塞IO
3)IO复用(select和poll)
4)信号驱动IO(sigio)
5)异步IO(aio_)
 
内核空间和用户空间:
由于操作系统都包括内核空间和用户空间(或者说内核态和用户态),内核空间主要存放的是内核代码和数据,是供系统进程使用的空间。而用户空间主要存放的是用户代码和数据,是供用户进程使用的空间。目前Linux系统简化了分段机制,使得虚拟地址与线性地址总是保持一致,因此,Linux系统的虚拟地址也是0~4G。Linux系统将这4G空间分为了两个部分:将最高的1G空间(从虚拟地址0xC0000000到0xFFFFFFFF)供内核使用,即为“内核空间”,而将较低的3G空间(从虚拟地址 0x00000000到0xBFFFFFFF)供用户进程使用,即为“用户空间”。同时由于每个用户进程都可以通过系统调用进入到内核空间,因此Linux的内核空间可以认为是被所有用户进程所共享的,因此对于一个具体用户进程来说,它可以访问的虚拟内存地址就是0~4G。另外Linux系统分为了四种特权级:0~3,主要是用来保护资源。0级特权最高,而3级则为最低,系统进程主要运行在0级,用户进程主要运行在3级。
 
一般来说,IO操作都分为两个阶段,就拿套接口的输入操作来说,它的两个阶段主要是:
1)等待网络数据到来,当分组到来时,将其拷贝到内核空间的临时缓冲区中
2)将内核空间临时缓冲区中的数据拷贝到用户空间缓冲区中
 
1、阻塞IO
默认情况下,所有套接口都是阻塞的。
假如recvfrom函数是一个系统调用:


说明:任何一个系统调用都会产生一个由用户态到内核态切换,再从内核态到用户态切换的过程,而进程上下文切换是通过系统中断程序来实现的,需要保存当前进程的上下文状态,这是一个极其费力的过程。
 
2、非阻塞IO
当我们把套接口设置成非阻塞时,就是由用户进程不停地询问内核某种操作是否准备就绪,这就是我们常说的“轮询”。这同样是一件比较浪费CPU的方式。


 
3、IO复用
我们常用到的IO复用,主要是select和poll。这里同样是会阻塞进程的,但是这里进程是阻塞在select或者poll这两个系统调用上,而不是阻塞在真正的IO操作上。
另外还有一点不同于阻塞IO的就是,尽管看起来与阻塞IO相比,这里阻塞了两次,但是第一次阻塞在select上时,select可以监控多个套接口上是否已有IO操作准备就绪的,而不是像阻塞IO那种,一次性只能监控一个套接口。


 
4、信号驱动IO
信号驱动IO就是说我们可以通过sigaction系统调用注册一个信号处理程序,然后主程序可以继续向下执行,当我们所监控的套接口有IO操作准备就绪时,由内核通知触发前面注册的信号处理程序执行,然后将我们所需要的数据从内核空间拷贝到用户空间。


 
5、异步IO
异步IO与信号驱动IO最主要的区别就是信号驱动IO是由内核通知我们何时可以进行IO操作了,而异步IO则是由内核告诉我们IO操作何时完成了。具体来说就是,信号驱动IO当内核通知触发信号处理程序时,信号处理程序还需要阻塞在从内核空间缓冲区拷贝数据到用户空间缓冲区这个阶段,而异步IO直接是在第二个阶段完成后内核直接通知可以进程后续操作了。


 
综上所述,我们发现 前四种IO模型的主要区别是在第一阶段,因为它们的第二阶段都是在阻塞等待数据由内核空间拷贝到用户空间;而异步IO很明显与前面四种有所不同,它在第一阶段和第二阶段都不会阻塞。具体参考如下:


 
最后,总结下同步IO与异步IO的区别:
1)同步IO操作会引起进程阻塞直到IO操作完成。
2)异步IO操作不引起进程阻塞。

因此,由上面定义可以看出,阻塞IO、非阻塞IO、IO复用、信号驱动IO都是属于同步IO,而异步IO模型才与异步IO定义所匹配。

### 操作系统 IO 知识点 #### 一、IO 多路复用机制 多路 IO 能够共用一个同步阻塞接口,当任意 IO 可操作时即可激活 IO 操作。这种模式是对传统阻塞 IO 的一种改进形式,在此情况下,真正的阻塞发生在 `select` 或者 `poll` 这样的系统调用上而非实际的 I/O 系统调用本身。利用这种方式,程序能够同时监控多个文件描述符的状态变化,一旦有任一描述符变为可读或者可写状态,则会触发相应的回调处理逻辑[^1]。 #### 二、系统调用的作用及其分类 为了保障计算机系统的安全性和稳定性,所有的应用程序都需要借助于特定的接口——即所谓的“系统调用”,来请求操作系统执行涉及硬件资源访问的任务。具体来说,这类任务涵盖了但不限于以下几个方面: - **设备管理**:负责管理和调度各类外部设备; - **文件管理**:提供文件创建、删除以及数据存取等功能支持; - **进程控制**:实现新进程建立、现有进程终止等一系列生命周期内的管理工作; - **进程间通讯**:构建起不同进程之间交流沟通所需的桥梁; - **内存分配**:合理规划并分发可用物理内存给各个正在运行的应用实例使用[^2]; #### 三、不同类型的数据传输方式 根据工作原理的不同,可以将常见的输入输出分为两大类别:字节流和字符流。前者是以8位为单位逐个传送原始比特序列;后者则是在此基础上加入了编码解码过程,使得所发送的信息更易于人类理解。除此之外还有专门用于解决两者互转场景下的技术方案可供选择[^3]。 #### 四、同步异步概念解析 对于编程而言,“同步”意味着发起方需等待接收端反馈之后才能继续向下推进后续流程;反之如果采用的是“异步”的话,则允许双方各自独立运作而不必相互牵绊。同样的道理也适用于阻塞与否的概念区分之上,只不过这里关注的重点变成了当前线程是否会因为等待某个事件的发生而暂停下来。 #### 五、Linux 下多种I/O模型概述 针对不同的应用场景需求,Linux 提供了至少五种主要类型的 I/O 模型以供开发者选用,其中包括最基础但也最容易造成性能瓶颈的传统阻塞式设计,到后来逐渐发展起来的各种优化版本如非阻塞、基于轮询的选择器(`select`)或是信号驱动等直至最新的完全意义上的异步化解决方案(AIO)。 ```java // Java 中关闭资源的例子 try (BufferedWriter writer = new BufferedWriter(new FileWriter("example.txt"))) { writer.write("Some text"); } catch (IOException e) { System.err.println(e); } finally{ try{if(writer != null)writer.close();}catch(IOException logOrIgnore){} } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值