0%

磁盘那些事儿

微服务架构的特点:“一解释就懂,一问就不知,一讨论就吵架”。

一、系统调用与内核

  1. 进程想要获取磁盘中的数据,而能和磁盘打交道的只能是内核,进程通知内核说要磁盘中的数据,此过程就是系统调用。
  2. 内核是一个操作系统的核心,是基于硬件的第一层软件扩充,提供操作系统的最基本的功能,是操作系统工作的基础。它负责管理系统的进程、内存、内核体系结构设备驱动程序、文件和网络系统,决定着系统的性能和稳定性。
    • 现代操作系统设计中,为减少系统本身的开销,往往将一些与硬件紧密相关的(如中断处理程序、设备驱动程序等)、基本的、公共的、运行频率较高的模块(如时钟管理、进程调度等)以及关键性数据结构独立开来,使之常驻内存,并对他们进行保护。通常把这一部分称之为操作系统的内核。

二、一次I/O过程

  1. 当进程发起系统调用时候,这个系统调用就进入内核模式,然后开始执行I/O操作。

  2. I/O操作分为两步:

    • 磁盘把数据装载进内核的内存空间
    • 内存空间的数据copy到用户的内存空间中,此过程才是真正I/O发生的地方

    I/O过程

  3. 过程分析:此进程需要对磁盘中的数据进行操作,则会向内核发起一个系统调用,然后此进程将会被切换出去,此进程会被挂起或者进入睡眠状态,也叫不可中断的睡眠,因为数据还没有得到,只有等到系统调用的结果完成后则进程会被唤醒,继续接下来的操作,从系统调用的开始到系统调用结束经过的步骤:

    • ①进程向内核发起一个系统调用
    • ②内核接收到系统调用,知道是对文件的请求,于是告诉磁盘,把文件读取出来
    • ③磁盘接收到来着内核的命令后,把文件载入到内核的内存空间里面
    • ④内核的内存空间接收到数据之后,把数据copy到用户进程的内存空间(此过程是I/O发生的地方)
    • ⑤进程内存空间得到数据后,给内核发送通知
    • ⑥内核把接收到的通知回复给进程,此过程为唤醒进程,然后进程得到数据,进行下一步操作

三、两种模式

  1. Reactor
  2. Proactor

四、五种模型

  1. 阻塞I/O(BIO):应用程序调用一个IO函数,导致应用程序阻塞,等待数据准备好。 如果数据没有准备好则一直等待。等数据准备好了,从内核拷贝到用户空间,IO函数返回成功指示。

阻塞I/O

阻塞I/O

  1. 非阻塞I/O(NIO):把一个套接口设置为非阻塞就是告诉内核,当所请求的I/O操作无法完成时不要将进程睡眠,而是返回一个错误。此后I/O操作函数将不断的测试数据是否已经准备好,如果没有准备好继续测试,直到数据准备好为止。在这个不断测试的过程中,会大量的占用CPU的时间。

非阻塞I/O

非阻塞I/O

  1. I/O多路复用:此模型会用到select、poll函数,这两个函数会使进程阻塞,但是和阻塞I/O所不同的是这两个函数可以同时阻塞多个I/O操作。此外还可以同时对多个读操作/写操作的I/O函数进行检测,直到有数据可读或可写时才真正调用I/O操作函数。2002年大神Davide Libenzi实现了epoll,修复了poll和select绝大部分问题。
    • 多路指的是多条独立的i/o流,i/o流可以这么理解:读是一条流(称之为读流,比如输入流),写是一条流(称之为写流,比如输出流),异常也是一条流(称之为异常流),每条流用一个文件描述符来表示,同一个文件描述符可以同时表示读流和写流。
    • 复用指的是线程,复用线程来跟踪每路i/o的状态,然后用一个线程就可以处理所有的i/o。
    • I/O多路复用简单来说就是一个线程追踪多条io流(读,写,异常),不使用轮询而是由设备本身告知程序哪条流可用了,这样一来就解放了cpu,也充分利用io资源。

I/O复用

I/O复用

  1. 事件(信号)驱动I/O:首先允许套接口进行信号驱动I/O,并安装一个信号处理函数,进程继续运行并不阻塞。当数据准备好时进程会收到一个SIGIO信号,可以在信号处理函数中调用I/O操作函数处理数据。

事件驱动I/O

事件驱动I/O

  1. 异步I/O(AIO):调用aio_read函数,告诉内核描述字、缓冲区指针、缓冲区大小、文件偏移及通知方式,然后立即返回。当内核将数据拷贝到缓冲区后,再通知应用程序。

异步I/O

异步I/O

  1. 几种I/O模型的比较

    前四种模型的区别是第一阶段基本相同,第二阶段基本相同,都是将数据从内核拷贝到调用者的缓冲区,而异步I/O的两个阶段都不同于前四个模型。

对比

对比

五、阻塞与非阻塞

阻塞和非阻塞关注的是程序在等待调用结果(消息,返回值)时的状态

  1. 阻塞调用是指调用结果返回之前,当前线程会被挂起,调用线程只有在得到结果之后才会返回。
  2. 非阻塞调用指在不能立刻得到结果之前,该调用不会阻塞当前线程,而会立刻返回。

六、同步与异步

同步和异步关注的是消息通信机制

  1. 同步:在发出一个调用时,在没有得到结果之前,该调用就不返回。但是一旦调用返回,就得到返回值了。
    • 如果“同步”是发起了一个调用后,没有得到结果之前不返回,那它毫无疑问就是被“阻塞”了,即调用进程处于waiting状态。
  2. 异步:在发出一个异步调用后,调用者不会立刻得到结果,而是在调用发出后,被调用者通过状态、通知来通知调用者,或通过回调函数处理这个调用。

同步/异步讨论的对象是双方, 而阻塞/非阻塞讨论的对象是自身。

七、I/O缓冲

八、参考

  1. reactor、proactor