# 基本概念

io是操作系统底层通过I/O指令完成,在Unix世界中一切皆文件,计算机通过使用文件描述符,也就是fd(一个整数),通过对这个整数的操作,对文件(流)进行操作,这是一种分层与抽象的方法。

# 交互流程

图展示了数据从外部磁盘向运行在用户空间的进程的内在区域移动的过程

JVM就是常规进程,驻守在用户空间

缓冲区及缓冲区如何工作,是所有IO的基础

虚拟内存映射:使用虚拟的地址取代物理内存地址,把内核空间地址与用户空间的虚拟地址映射到同一个物理地址,这样,DMA硬件就可以填充对内核和用户空间进程同时可以使用的缓冲区。从而省去在内核和用户空间往来拷贝

memory-multi

内存映射 I/O :使用文件系统建立从用户空间到可用文件系统的虚拟内在映射

  1. 把文件数据当做内存,无需发起read和write的系统调用
  2. 使用时,页错误自动产生,从而将文件数据从磁盘读到内在,同样如果个性了映射内在空间,相关页会标记为脏,刷新到磁盘文件
  3. 虚拟内在子系统会对页进行智能高速缓存,自动根据系统负载进行内存管理
  4. 数据按页对齐,不需要进行缓冲区拷贝
  5. 大型文件不需要使用大量内存就可进行数据拷贝

file-memory

# IO

# 阻塞IO

用户进程告诉内核启动某个操作后,一直等到内核操作完成后,程序才可处理数据

IO执行的两个阶段(等待数据和拷贝数据两个阶段)都被阻塞

block-io

# 非阻塞IO

用户程序每隔一段时间询问内核是否有数据准备好(文件描述符缓冲区是否就绪),当有数据准备好时,进行数据拷贝的操作。如果没有准备好的,不阻塞程序,内核返回未准备就绪的信号

非阻塞式IO中、用户进程其实是需要不断的主动询问kernel数据准备好了没有

no-block

# 信号驱动

用户程序告诉内核,当有数据准备好时,发一个信号,并且调用用户程序的信号处理函数来获取数据报

信号处理的开销有点大

sign-io

# IO多路复用

IO多路转接,通过select函数,对文件描述符集合进行循环监听,当某个文件描述符就绪,对它进行处理。本质属于阻塞IO,但由于同时可以对多个描述符进行阻塞监听,效率较高

在IO复用模型中、对于每一个socket、一般都设置成为非阻塞、但是、如上图所示、整个用户的进程其实是一直被阻塞的、只不过进程是被select这个函数阻塞、而不是被socket IO给阻塞

io-multi

# 异步IO

用户进程告知内核启动某个操作、并让内核在整个操作完成后通知我们

在异步IO模型中、真正实现了POSIX描述的异步IO、是五种IO模型中唯一的异步模型

用户进程发起aio_read(POSIX异步IO函数aio_或者lio_开头)操作之后、给内核传递描述符、缓冲区指针、缓冲区大小和read相同的三个参数以及文件偏移(与lseek类似)、告诉内核当整个操作完成时、如何通知我们、立刻就可以开始去做其它的事

从内核的角度、当它受到一个aio_read之后、首先它会立刻返回、所以不会对用户进程产生任何阻塞、然后、内核会等待数据准备完成、然后将数据拷贝到用户内存、当这一切都完成之后、内核会给用户进程发送一个信号、告诉它aio_read操作完成了

async-io

# 5种IO比较

  1. Block与NoBlock 是否阻塞住对应的进程直到操作完成,非阻塞IO在内核未准备数据情况下立即返回,关注的是进程在等待调用结果时的状态

  2. 同步异步 做IO操作时是否会将进程阻塞

    非阻塞IO在执行recvfrom系统调用时,如果内核没有准备好,不会阻塞进程,但是当数据准备好时,recvfrom会把数据从内核拷贝到用户内在,这个过程是阻塞了,信号驱动同样的道理。

上次更新: : 5 months ago