• 五种IO模型


    五种I/O模型

    • 阻塞I/O
    • 非阻塞I/O
    • 信号驱动I/O
    • 多路转接(多路复用) I/O
    • 异步I/O

    前面四种属于同步IO模型


    预备知识
    I/O的两个步骤:

    • (1)等待I/O事件就绪。
      就是等待内核将数据准备好
    • (2)执行I/O操作。
      将数据从内核缓冲区读入用户缓冲区,或者将数据从用户缓存区写入内核缓冲区。所谓的读入和写入本质是将数据拷贝过来、拷贝过去。

    阻塞的文件描述符称为阻塞I/O;
    I/O阻塞执行的系统调用,如果相关事件没有就绪,意味着不能被立即完成,此时就会被操作系统挂起,直到被等待事件就绪。
    在这里插入图片描述

    • 如果内核还没有将数据准备好,系统调用仍然会直接返回,并且设置EWOULDBLOCK错误码。

    所有的套接字创建的时候默认都是阻塞的,套接字API中,可能被阻塞的系统调用包括accept、send、recv、connect。


    非阻塞的文件描述符称为非阻塞I/O;
    非阻塞I/O执行的系统调用,不管相关事件是否发生,总是立即返回。往往需要程序员使用循环的方式返回尝试读写文件描述符,这个过程称为轮询。
    在这里插入图片描述
    如果等待的事件没有立即发生,这些系统调用会以出错的形式返回的。其实它不是真正地调用失败,事件未就绪真正的调用出错都是以出错的形式返回,区分这两个情况的关键在于错误码:

    • 非阻塞I/O事件未就绪设置错误码
      (1)accept、send、recv而言,错误码通常被设置为EAGAIN(“再来一次”)/EWOULDBLOCK(“期望阻塞”)。
      (2)connect而言,错误码通常被设置为EINPROGRESS(“在处理中”)。

    显然,非阻塞I/O很容易浪费CPU资源,通常不单独使用,而是和其他I/O通知机制一起使用


    信号驱动I/O
    可以为目标文件描述符指定宿主进程,这个进程将捕获到SIGIO信号。当内核将该目标文件描述符上的IO事件准备就绪时,会使用SIGIO信号通知应用进程进行I/O操作,然后SIGIO信号的信号处理函数会被触发。我们可以在SIGIO信号处理函数内部对目标文件描述符执行非阻塞I/O操作。
    在这里插入图片描述


    多路复用I/O
    应用进程通过I/O复用函数向内核注册一组事件,能够同时等待多个文件描述符的I/O事件就绪,内核通过I/O复用函数将其中就绪的事件通知给应用进程。
    在这里插入图片描述
    Linux上常用的I/O复用函数:select、poll、epoll_wait。

    注意:

    • 程序阻塞于I/O复用系统调用,而对I/O本身的读写操作是非阻塞的。
    • 多路复用是同步I/O中最高效的I/O模型,原因在于它们具有同时监听多个I/O事件的能力。

    异步I/O
    内核在数据拷贝完成后,通知应用程序(信号驱动是告诉应用程序何时开始拷贝数据)。
    在这里插入图片描述

    同步I/O与异步I/O的区别:

    • 同步I/O要求用户自行执行I/O操作。内核将数据准备好后,由用户自己进行读写操作。
    • 异步I/O由内核执行I/O操作。用户直接执行I/O操作,会告诉内核用户读写缓冲区的位置,以及I/O操作完成后内核通知应用程序的方式,接下来的I/O操作就交由内核接管。

    Linux的aio.h头文件中定义了支持异步I/O的函数。


    I/O模型阻塞阶段
    阻塞I/O阻塞于读写函数
    非阻塞I/O无阻塞阶段
    信号驱动I/O无阻塞阶段
    多路复用I/O阻塞于I/O复用系统调用,对I/O本身的读写操作是非阻塞的
    异步I/O无阻塞阶段
  • 相关阅读:
    猿创征文|有了这8个开发工具,程序员可以早点下班了
    Vue中引入一个异步组件
    精心整理了超详细的Linux入门笔记,零基础也能看懂,一学就会
    正则表达式
    SpringBoot2.0(mybatis-plus常见的增删改查和分页)
    Flutter 如何启动新的页面时给页面传递参数
    性能优化之分页查询 | StartDT Tech Lab 12
    ​电脑上的回收站怎么隐藏 ,怎么隐藏桌面回收站图标
    软件工程与计算总结(二十)软件交付
    低价链接,平台投诉,你真的会吗
  • 原文地址:https://blog.csdn.net/qq_56870066/article/details/126902587