PPXu

几张图总结几种I/O类型

2018-11-20

Unix/Linux支持的5种I/O类型:

  • 同步模型(synchronous IO)
    • 阻塞IO(bloking IO)
    • 非阻塞IO(non-blocking IO)
    • 多路复用IO(multiplexing IO)
    • 信号驱动式IO(signal-driven IO)
  • 异步IO(asynchronous IO)

过程图解

阻塞



非阻塞



多路复用



信号驱动



异步

怎么理解

I/O过程分两个阶段:

  1. 数据从硬件(网卡、硬盘)拷贝到内核的内存空间。
  2. 数据从内核的内存空间拷贝到用户态的内存空间
    为什么要分两个阶段? (撇开零拷贝不说)前提是用户态程序(应用程序)不能直接跟硬件打交道,而能与硬件打交道的就只能是内核,用户态程序要想从硬件获得数据,必须通知内核我要获得硬件中的数据,此过程称为系统调用,为第一阶段。 于是,自然就有了第二阶段,数据从内核内存空间到用户态内存空间。(对用户态来讲,此过程才是I/O发生的地方)

概括每种I/O类型的过程

OK,有了两阶段的概念后,可以简单来理解并总结每种I/O类型的过程:

一图胜千言:

浅谈零拷贝

既然提到零拷贝,那就粗浅地说明一下:
零拷贝是指,减免了数据在内核空间和用户空间来回拷贝(无cpu copy过程)。


用户态程序调用mmap(),磁盘上的数据会通过DMA(直接内存存取,direct memory access,一种透过DMA控制器让内存与硬盘/网卡直接对接的IO技术,过程中无需依赖CPU的大量中断负载)被拷贝到内核缓冲区,接着操作系统会把这段内核缓冲区与应用程序共享,这种所谓的共享,方式就是mmap(内存映射,memory map),这样就不需要把内核缓冲区的内容往用户空间拷贝。用户态程序再调用write(),操作系统直接将内核缓冲区的内容拷贝到socket缓冲区中,这一切都发生在内核态,最后,socket缓冲区再把数据发到网卡去。


好吧,一图胜千言:

OK,上面所说的DMA技术直接让内存对接硬盘IO,以及mmap让用户程序共享内核缓冲区,都可以省掉内核空间与用户空间之间的cpu copy,但是还有个问题,就是内核与socket缓冲区之间是否也可以免掉一次CPU copy呢?借助于硬件上的帮助,我们是可以办到的。之前我们是把页缓存的数据拷贝到socket缓存中,实际上,我们仅仅需要把缓冲区描述符传到socket缓冲区,再把数据长度传过去,这样DMA控制器直接将页缓存中的数据打包发送到网络(网卡)中去就可以了。这样,就是可以实现真正的全程零CPU拷贝了。

Reference

《UNIX网络编程》

浅析Linux中的零拷贝技术

扫描二维码,分享此文章