IO分类和IO模型

IO分类和IO模型

Posted by zhaostu4 on November 28, 2019

T:2019/11/28 W:四 17:0:11 [HTML]: @TOC

前言

1) 什么是 I/O? - I/O输入/输出(Input/Output),分为IO设备和IO接口两个部分。 2) UnixLinux的区别? - UNIX是一个功能强大、性能全面的多用户、多任务操作系统,可以应用从巨型计算机到普通PC机等多种不同的平台上,是应用面最广、影响力最大的操作系统。(收费的商业软件) - Linux 是一种外观和性能与UNIX相同或更好的操作系统,但,Linux不源于任何版本的UNIX的源代码,并不是UNIX,而是一个类似于UNIX的产品。(开源/免费的软件) 3) 什么是I/O操作,什么是文件描述? - unix(like)世界里,一切皆文件,而文件是什么呢?文件就是一串二进制流而已,不管socket,还是FIFO、管道、终端,一切都是文件,一切都是流。在信息 交换的过程中,我们对这些流进行数据的收发操作,简称为I/O操作(input and output),从数据流中读取数据,系统会调用read(读取数据);写入数据,系统调用write(写入数据)。不过话说回来了 ,计算机里有这么多的流,我怎么知道要操作哪个流呢?对,就是文件描述符,即通常所说的fd,一个fd就是一个整数,所以,对这个整数的操作,就是对这个文件(流)的操作。我们创建一个socket,通过系统调用会,返回一个文件描述符,那么剩下对socket的操作就会转化为对这个描述符的操作。不能不说这又是一种分层和抽象的思想。

I/O分类

  • 同步IO, 异步IO, 阻塞IO, 非阻塞IO区别联系
  • 分析
    • 实际上同步与异步是针对应用程序与内核的交互而言的。
      • 同步过程中进程,触发IO操作并等待(也就是阻塞)或者轮询的去查看IO操作(也就是非阻塞)是否完成。
      • 异步过程中进程触发IO操作以后,直接返回,做自己的事情,IO交给内核来处理,完成后内核通知进程IO完成。
    • 同步和异步对应用程序而言关注的是内核与进程中间的协作关系;
    • 阻塞与非阻塞更关注的是单个进程的执行状态。
    • 同步有阻塞和非阻塞之分,异步没有,异步一定是非阻塞的。
    • 阻塞、非阻塞、多路IO复用,都是同步IO,异步必定是非阻塞的,所以不存在异步阻塞和异步非阻塞的说法。
    • 真正的异步IO需要内核的深度参与。换句话说,只有用户线程在操作IO的时候根本不去考虑IO的执行全部都交给内核去完成,而自己只等待一个完成信号的时候,才是真正的异步IO。所以,用一个子线程去轮询、去死循环,或者使用select, poll, epool, 都不是异步。
  • 结论:
    • 同步:执行一个操作之后,进程触发IO操作并等待(也就是我们说的阻塞)或者轮询的去查看IO操作(也就是我们说的非阻塞)是否完成,等待结果,然后才继续执行后续的操作。
    • 异步:执行一个操作后,可以去执行其他的操作,然后等待通知再回来执行刚才没执行完的操作。
    • 阻塞:进程给内核传达一个任务之后,一直等待内核处理完成,然后才执行后面的操作。
    • 非阻塞:进程给内核传达任我后,继续处理后续的操作,隔断时间再来询问之前的操作是否完成。这样的过程其实也叫轮询。

      I/O模型

  • 阻塞I/O模型(BIO)
    • 最广泛的模型是阻塞I/O模型,默认情况下,所有套接口都是阻塞的。 进程调用recvfrom系统调用,整个过程是阻塞的,直到数据复制到进程缓冲区时才返回(当然,系统调用被中断也会返回)。
  • 非阻塞I/O模型(NIO)
    • 当我们把一个套接口设置为非阻塞时,就是在告诉内核,当请求的I/O操作无法完成时,不要将进程睡眠,而是返回一个错误。当数据没有准备好时,内核立即返回EWOULDBLOCK错误,第四次调用系统调用时,数据已经存在,这时将数据复制到进程缓冲区中。这其中有一个操作时轮询(polling)
  • 异步I/O模型(AIO)
    • 进程发起read操作之后,立刻就可以开始去做其它的事。而另一方面,从kernel的角度,当它受到一个asynchronous read之后,首先它会立刻返回,所以不会对用户进程产生任何block。然后,kernel会等待数据准备完成,然后将数据拷贝到用户内存,当这一切都完成之后,kernel会给用户进程发送一个signal,告诉它read操作完成了。
    • 这个模型工作机制是:告诉内核启动某个操作,并让内核在整个操作(包括第二阶段,即将数据从内核拷贝到进程缓冲区中)完成后通知我们。
    • 这种模型和前一种模型区别在于:信号驱动I/O是由内核通知我们何时可以启动一个I/O操作,而异步I/O模型是由内核通知我们I/O操作何时完成。
  • 信号驱动I/O模型(signal driven I/O SIGIO)
    • 首先我们允许套接口进行信号驱动I/O,并安装一个信号处理函数,进程继续运行并不阻塞。当数据准备好时,进程会收到一个SIGIO信号,可以在信号处理函数中调用I/O操作函数处理数据。当数据报准备好读取时,内核就为该进程产生一个SIGIO信号。我们随后既可以在信号处理函数中调用recvfrom读取数据报,并通知主循环数据已准备好待处理,也可以立即通知主循环,让它来读取数据报。无论如何处理SIGIO信号,这种模型的优势在于等待数据报到达(第一阶段)期间,进程可以继续执行,不被阻塞。免去了select的阻塞与轮询,当有活跃套接字时,由注册的handler处理。
  • I/O多路复用
    • I/O复用模型用到selectpoll函数,这两个函数也会使进程阻塞,select先阻塞,有活动套接字才返回,但是和阻塞I/O不同的是,这两个函数可以同时阻塞多个I/O操作,而且可以同时对多个读操作,多个写操作的I/O函数进行检测,直到有数据可读或可写(就是监听多个socket)select被调用后,进程会被阻塞,内核监视所有select负责的socket,当有任何一个socket的数据准备好了,select就会返回套接字可读,我们就可以调用recvfrom处理数据。
    • 正因为阻塞I/O只能阻塞一个I/O操作,而I/O复用模型能够阻塞多个I/O操作,所以才叫做多路复用。