博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Linux异步I/O
阅读量:4109 次
发布时间:2019-05-25

本文共 2593 字,大约阅读时间需要 8 分钟。

        Linux中最常用的输入/输出(I/O)模型是同步I/O。在这个模型中,当请求发出之后,应用程序就会阻塞,直到请求满足为止。这是很好的一种解决方案,因为调用应用程序在等待I/O请求完成时不需要占用任何CPU时间。但是在某些情况中,I/O请求可能需要与其他进程产生交叠。可移植操作系统接口(POSIX)异步I/O(AIO)应用程序接口(API)就提供了这种功能。在本文中,我们将对这个API概要进行介绍,并来了解一下如何使用它。

  • AIO简介

        Linux异步I/O是Linux内核中提供的一个相当新的增强。它是2.6版本内核的一个标准特性,但是我们在2.4版本内核的补丁中也可以找到它。AIO背后的基本思想是允许进程发起很多I/O操作,而不用阻塞或等待任何操作完成。稍后或在接收到I/O操作完成的通知时,进程就可以检索I/O操作的结果。

图1  基本Linux I/O模型的简单矩阵

        每个I/O模型都有自己的使用模式,它们对于特定的应用程序都有自己的优点。本节将简要对其一一进行介绍。

  • 同步阻塞I/O

        最常用的一个模型是同步阻塞I/O模型。在这个模型中,用户空间的应用程序执行一个系统调用,它会导致应用程序阻塞。这意味着应用程序会一直阻塞,直到系统调用完成为止(数据传输完成或发生错误)。执行系统调用的应用程序处于一种不再消费CPU而只是简单等待响应的状态,因此从处理的角度来看,这是非常有效的。

        图2给出了传统的阻塞I/O模型,这也是目前应用程序中最为常用的一种模型。其行为非常容易理解,其用法对于典型的应用程序来说都非常有效。在调用read系统调用时,应用程序会阻塞并对内核进行上下文切换。然后会触发读操作,当响应返回时(从我们正在从中读取的设备中返回),数据就被移动到用户空间的缓冲区中,接着应用程序就会解除阻塞(read调用返回)。

图2  同步阻塞I/O模型的典型流程

        从应用程序的角度来说,read调用会延续很长时间。实际上,在内核执行读操作和其他工作时,应用程序的确会被阻塞。

  • 同步非阻塞I/O

        同步阻塞I/O的一种效率稍低的变种是同步非阻塞I/O。在这种模型中,设备是以非阻塞的形式打开的。这意味着I/O操作不会立即完成,read操作可能会返回一个错误代码,说明这个命令不能立即满足(EAGAIN或EWOULDBLOCK),如图3所示。

图3  同步非阻塞I/O模型的典型流程

        非阻塞的实现是I/O命令可能并不会立即满足,需要应用程序调用许多次来等待操作完成。这可能效率不高,因为在很多情况下,当内核执行这个命令时,应用程序必须要进行忙碌等待,直到数据可用为止,或者试图执行其他工作。正如图3所示的一样,这个方法可以引入I/O操作的延时,因为数据在内核中变为可用到用户调用read返回数据之间存在一定的间隔,这会导致整体数据吞吐量的降低。

  • 异步阻塞I/O

        另外一个阻塞解决方案是带有阻塞通知的非阻塞I/O。在这个模型中,配置的是非阻塞I/O,然后使用阻塞select系统调用来确定一个I/O描述符何时有操作。使select调用非常有趣的是它可以用来为多个描述符提供通知,而不仅仅为一个描述符提供通知。对于每个提示符来说,我们可以请求这个描述符可以写数据、有读数据可用以及是否发生错误的通知。

图4  异步阻塞I/O模型的典型流程(select)

        select调用的主要问题是它的效率不是非常高。尽管这是异步通知使用的一种方便模型,但是对于高性能的I/O操作来说不建议使用。

  • 异步非阻塞I/O(AIO)

        异步非阻塞I/O模型是一种CPU处理与I/O重叠进行的模型。读请求会立即返回,说明read请求已经成功发起了。在后台完成读操作时,应用程序会执行其它处理操作。当read的响应到达时,就会产生一个信号或执行一个基于线程的回调函数来完成这次I/O处理过程。

图5  异步非阻塞I/O模型的典型流程

        在一个进程中为了执行多个I/O请求而对计算操作和I/O处理进行重叠处理,这种能力利用了处理速度与I/O速度之间的差异。当一个或多个I/O请求挂起时,CPU可以执行其他任务;或者更为常见的是,在发起其他I/O的同时对已经完成的I/O进行操作。

  • 异步I/O的动机

        从前面I/O模型的分类中,我们可以看出AIO的动机。这种阻塞模型需要在I/O操作开始时阻塞应用程序,这意味着不可以用时重叠进行CPU处理和I/O操作。同步非阻塞模型允许CPU处理和I/O操作重叠进行,但是这需要应用程序根据重现的规则来检查I/O操作的状态。这样就剩下异步非阻塞I/O了,它允许CPU处理和I/O操作重叠进行,包括I/O操作完成的通知。

        除了需要阻塞之外,select函数所提供的功能(异步阻塞I/O)与AIO类似。不过,它是对通知事件进行阻塞,而不是对I/O调用进行阻塞。

  • Linux上的AIO简介

        本节将探索Linux的异步I/O模型,从而帮助我们理解如何在应用程序中使用这项技术。在传统的I/O模型中,有一个使用唯一句柄的I/O通道。在UNIX中,这些句柄是文件描述符(这等同于文件、管道、套接字等等)。

        在阻塞I/O中,我们发起了一次传输操作,当传输操作完成或发生错误时,系统调用就会返回。

        在异步非阻塞I/O中,我们可以同时发起多个传输操作。这需要每个传输操作都有唯一的上下文,这样我们才能在它们完成时区分到底是哪个传输操作完成了。在AIO中,这是一个aiocb(AIO I/O Control Block)结构。这个结构包含了有关传输的所有信息,包括为数据准备的用户缓冲区。在产生I/O(称为完成)通知时,aiocb结构就被用来唯一标识所完成的I/O操作。这个API的展示显示了如何使用它。

  • AIO API

        AIO接口的API非常简单,它为数据传输提供了必需的功能,并给出了两个不同的通知模型。以下是AIO的接口函数:

          1) aio_read,请求异步读操作。

          2) aio_error,检查异步请求的状态。

          3) aio_return,获得完成的异步请求的返回状态。

          4) aio_write,请求异步写操作。

          5) aio_suspend,挂起调用进程,直到一个或多个异步请求已经完成(或失败)。

          6) aio_cancel,取消异步I/O请求。

          7) aio_listio,发起一系列I/O操作。

你可能感兴趣的文章
有return的情况下try catch finally的执行顺序(最有说服力的总结)
查看>>
String s1 = new String("abc"); String s2 = ("abc");
查看>>
JAVA数据类型
查看>>
Xshell 4 入门
查看>>
SoapUI-入门
查看>>
Oracle -常用命令
查看>>
JAVA技术简称
查看>>
ORACLE模糊查询优化浅谈
查看>>
2016——个人年度总结
查看>>
2017——新的开始,加油!
查看>>
【Python】学习笔记——-6.2、使用第三方模块
查看>>
【Python】学习笔记——-7.0、面向对象编程
查看>>
【Python】学习笔记——-7.1、类和实例
查看>>
【Python】学习笔记——-7.2、访问限制
查看>>
【Python】学习笔记——-7.3、继承和多态
查看>>
【Python】学习笔记——-7.4、获取对象信息
查看>>
【Python】学习笔记——-7.5、实例属性和类属性
查看>>
Linux设备模型(总线、设备、驱动程序和类)之四:class_register
查看>>
git中文安装教程
查看>>
虚拟机 CentOS7/RedHat7/OracleLinux7 配置静态IP地址 Ping 物理机和互联网
查看>>