操作系统IO机制

  身处不同的学习阶段时,总会对不同的知识有不同的理解,最近感慨其实计算机就是在计算和IO这两件事情上反复执行,最后完成一系列指令,虽然之前写过一篇NIO epoll的文章,但这里还是专门为操作系统的IO机制开辟一篇专栏,一起再来整理一下IO这一重要事件的机制。

同步与异步

  网上讲这块的内容很多,烂熟的烧开水例子相信大家都不陌生,总之,说同步和异步时,需要肯定的是这两个概念说明的是多个事物的状态,而不是单个事物的状态,多个事物串行,但每次只执行一个事物,这样的状态称为同步,至于其他事物一般来说都是在等待着的状态,可以联系的生活中的场景有排队买票等;异步与同步是相反的状态,异步是指,多个事物可以互不干扰的同时进行,比如地铁闸机口可以允许多人在多个通道同时通过一样。

阻塞与非阻塞

  这两个也是相反的状态,其实从字面意思已经看出十之八九,阻塞指的是线程在调用某方法的时候会被挂起,等到g方法返回结果时才会恢复运行;非阻塞指的是线程在调用某方法时立即返回一个信号,但这个信号不是方法的结果,它是一个仅仅表示调用方法的返回值,在等待方法执行的过程中,该线程还可以继续去干其他事情。
  综上所述,同步与异步关心的点在于能否同时进行,阻塞与非阻塞关心的点在于是否需要等待。

IO

  IO就是数据的读出和写入的过程及等待数据读出和写入的过程,注意哦,这里我们还是要强调一下,IO不仅包括数据读出写入的过程,还包括等待数据读出和写入的过程,但还需牢记,一旦数据读出写入完成,剩下的操作数据的过程不属于IO的范围。
在Linux系统中,我们常见的IO机制有以下几种:
阻塞IO
非阻塞IO
多路复用IO
异步IO

阻塞IO与非阻塞IO

阻塞IO

  结合以上说的概念,再延伸一下,阻塞IO指的是应用程序发出一个阻塞系统的调用时,在等待数据到达用户空间的过程中,应用程序的执行被挂起,应用程序从操作系统的运行队列加入等待队列,等到系统调用完成后,应用程序移回到运行队列中。

非阻塞IO

  非阻塞IO,按上面说的IO的两个过程细分一下,等待数据到达用户空间(非阻塞)及在用户空间发生拷贝(阻塞)的这两个过程中,所以非阻塞IO主要是说明,用户进程不会阻塞于等待数据达到用户空间的过程中,此时它会多次发起系统调用,并马上返回错误的结果,直到数据到达用户空间会返回OK,然后继续执行拷贝,但拷贝的过程是阻塞的。所以这种方式严格一点来说,并不能将全部的过程都称为非阻塞IO,这种轮询的方式,会消耗CPU资源。

多路复用IO

  多路复用其实是一种同步非阻塞的IO方式,epoll就是多路复用的典型,多路复用从select、poll、epoll一路进阶,详细的过程可以看专门写epoll的那篇文章,总之它的过程就是用户进程在等待数据到达用户空间的过程中,epoll会监听所有的socket,用户进程也会加入epoll的等待队列,当某一个socket接收数据,epoll会把收到数据的socket加入自己的list,从而得知是具体的哪个socket收到了数据,并唤醒等待这个socket的进程,不知道在我刚刚的描述中,你是否能感受到多路复用的好处,epoll相比select的好处是无需去轮询,但在等待数据到达的这个过程,还是一个阻塞的状态。以上过程中有一点要注意,对于用户进程来说,在等待数据到用户空间的过程中,其实它是阻塞于epoll的,它要等待epoll获悉具体的某一个socket收到数据后唤醒它;但对于socket来说,数据从网络传递进来需要一个过程,它等待数据的过程中,没有阻塞挂起,是非阻塞的。所以我们说的多路复用是一直同步非阻塞的方式,如果从用户进程的角度来说,好像不够严谨。
  通过以上这些过程也能发现,阻塞IO,用户程序在等待IO及拷贝的过程是线程挂起的,相当于就还是只能允许一个线程的进行,所以阻塞IO无论如何都是同步的。

异步IO

  异步IO使用率不如之前的高,所以在这里简单的说一下,它不难理解,总是还是按照我们说的那两个过程去看,在等待数据到达的过程及数据拷贝的过程,用户进程都不会死等阻塞,而是去干自己的事情,当数据完成从内核空间到用户空间的拷贝后,才会通知用户进程。这样看来,异步IO都是非阻塞的。

非阻塞和异步IO的区别

  非阻塞和异步IO,甚至会认为非阻塞就是异步了,其实不然,一次IO操作分两个阶段,第一阶段是等待数据,第二阶段是拷贝数据(内核到用户空间),非阻塞IO操作在数据还没有到达时是立即返回的,这一点表现的跟异步一样,但是在第二个阶段,当数据准备妥当的时候,非阻塞IO是阻塞的,直到数据拷贝完成,这一点表现的与异步IO完全不一样,异步根本不关心你的数据是否到达以及你的数据是否拷贝完成,异步发起一次IO操作后就去干别的事儿了,直到内核发出一个信号通知这一事件,它才会转回来继续处理。

小结

  IO过程主要有两个部分:等待数据(比如从网卡到达内核空间)、读写数据(从内核空间拷贝到用户空间),前三种关于阻塞IO和非阻塞IO的划分,主要是针对等待数据这个过程而言,因为从内核空间拷贝到用户空间的这个过程它们都是阻塞的。异步IO不会引起用户进程的阻塞。

你可能感兴趣的:(操作系统IO机制)