• Linux 网络I/O模型


    前言

         本文是笔者的第一篇博文,在这篇文章的大部分内容基于steven大神的《Unix Network Programming》。一来是对书本内容的整理与归纳。二来也是为接下来的博文奠定基础。

         在实际应用中,数据操作通常分为输入和输出,那么以输入为例,在操作系统中,一个数据的输入通常分为以下两个过程:

    1. 等待数据准备好.
    2. 将准备好的数据从内核拷贝到用户空间

         下面我们将会分别讨论 I/O 模型中的两个大类,即 同步 I/O 与 异步 I/O。

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

    同步阻塞I/O

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

           图 2. 同步阻塞 I/O 模型

    同步非阻塞 I/O

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

          图 3. 同步非阻塞 I/O 模型

          当一个应用进程像这样对一个非阻塞描述符循环调用recvfrom时,我们称之为轮询(polling)。应用进程只需轮询内核,以查看某个操作是否就绪。这么做往往耗费大量CPU时间。

    I/O复用模型

          I/O 复用有时又被称为 事件驱动 I/O, 它的最大优势在于,我们可以将感兴趣的多个I/O事件(更精确的说,应该是 I/O 所对应的文件描述符)注册到 select/poll/epoll/kqueue 之中某一个系统调用上(很多时候,这些系统调用又被称为多路复用器。假设此时我们选择了 select() )。此后,调用进程会阻塞在 select() 系统调用之上(而不是阻塞在真正的 I/O 系统调用(如 read(), write() 等)上)。select() 会负责监视所有已注册的 I/O 事件,一旦有任意一个事件的数据准备好,那么 select() 会立即返回,此时我们的用户进程便能够进行数据的复制操作。

            图 4.  I/O复用模型

         总而言之,I/O 复用的优点就在于可以同时等待多个I/O事件;而缺点是会进行两次系统调用(一次 select(), 一次 read() )。

    信号驱动式I/O模型

         在这种模型下,我们首先开启套接字的信号驱动式I/O功能,并通过sigaction系统调用安装一个信号处理函数。改系统调用将立即返回,我们的进程继续工作,也就是说他没有被阻塞。当数据报准备好读取时,内核就为该进程产生一个SIGIO信号。我们随后就可以在信号处理函数中调用read读取数据报,并通知主循环数据已经准备好待处理,也可以立即通知主循环,让它读取数据报。

           图 5. 信号驱动I/O模型

         无论如何处理SIGIO信号,这种模型的优势在于等待数据报到达期间进程不被阻塞。主循环可以继续执行,只要等到来自信号处理函数的通知:既可以是数据已准备好被处理,也可以是数据报已准备好被读取。

    异步非阻塞 I/O

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

          图 6. 异步非阻塞I/O模型

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

    各种I/O模型的比较

          通过上面的讨论可以清楚的看到,同步 I/O 总会有阻塞的过程,这就是“同步”最本质的特征。而如前文所说,异步 I/O 的最大特点在于用户进程均不阻塞。 用户进程告知内核启动某一 I/O 操作, 并让内核全权代为执行(包括等待数据及拷贝数据至用户空间),此后用户进程可以立即执行其它的任何操作。等到所有 I/O 过程执行完成后, 内核会通知用户程。由此可见,在整个过程中,用户进程均不阻塞。

           图 7. 各种I/O模型的比较1

          图 8 . I/O 模型比较2
              I/O模型                                                               读写操作和阻塞阶段
              阻塞I/O                                                                应用阻塞于读写函数
              I/O复用                     应用阻塞于I/O复用系统调用,但可同时监听多个I/O事件。对I/O本身的读写操作是非阻塞的
           信号驱动I/O                                     信号触发读写就绪事件,用户程序执行读写操作。应用没有阻塞阶段
              异步I/O                                     内核执行读写操作并触发读写完成事件。应用没有阻塞阶段

    参考

        《Unix Network Programming》(volume 1)

        《使用异步 I/O 大大提高应用程序的性能

     

  • 相关阅读:
    ArcGIS学习记录—union、merge及append的区别
    ArcGIS学习记录—属性表的编辑与修改
    ASP.NET应用程序和ASP.NET网站所共有的文件: App_Browsers 等
    C# 文件夹操作
    远程重启服务器
    SQL省市区三级表结构
    c#提出中文首字母
    javascript遍历Json对象个数
    原生javascript添加引用js文件
    简单的div蒙层
  • 原文地址:https://www.cnblogs.com/lojunren/p/3850057.html
Copyright © 2020-2023  润新知