理解阻塞I/O和非阻塞I/O,同步I/O和异步I/O

首先需要明确一下系统调用的概念:当运行在用户空间的程序需要向内核请求更高权限的服务时,需要进行系统调用,它提供操作系统和用户程序之间的接口,类似于普通库函数,但是由操作系统内核提供并运行于内核态,而普通库函数由函数库或用户自己提供并运行于用户态。因此,进行系统调用时会经历从用户态转到内核态运行一段时间,然后再转回到用户态的过程。

阻塞I/O和非阻塞I/O

阻塞I/O:系统调用会被操作系统挂起,直至等待的事件发生位置。

非阻塞I/O:系统调用会立刻返回,不管事件有没有发生。若事件没有发生或出错,均返回-1,并设置相应的errno。然后,每隔一段时间再调用系统函数,查看事件有没有发生。

因此,阻塞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和异步I/O的主要区别就是I/O操作由谁执行。

五种I/O模型

这里讨论的五种I/O模型分别是:阻塞I/O模型、非阻塞I/O模型、I/O复用模型、信号驱动I/O模型以及异步I/O模型,其中,前面四种均是同步I/O。

下面使用Linux下的系统调用recv作为例子来分别讨论这五种模型,recv用于从套接字上接收一个消息。

阻塞I/O模型

使用recv的默认参数一直等数据直到拷贝到用户空间,这段时间内进程始终阻塞。
在这里插入图片描述

非阻塞I/O模型

改变flags,让recv不管有没有获取到数据都返回,如果没有数据那么一段时间后再调用recv看看,如此循环。
在这里插入图片描述

I/O复用模型

这里在调用recv前先调用select或者poll,这2个系统调用都可以在内核准备好数据(网络数据到达内核)时告知用户进程,这个时候再调用recv一定是有数据的。因此这一过程中它是阻塞于select或poll,而没有阻塞于recv,有人将非阻塞IO定义成在读写操作时没有阻塞于系统调用的IO操作(不包括数据从内核复制到用户空间时的阻塞,因为这相对于网络IO来说确实很短暂)。这种IO模型比较特别,分个段。因为它能同时监听多个文件描述符(fd)。
在这里插入图片描述

信号驱动I/O模型

通过调用sigaction注册信号函数,等内核数据准备好的时候系统中断当前程序,执行信号函数(在这里面调用recv)。
在这里插入图片描述

异步I/O模型

调用aio_read,让内核等数据准备好,并且复制到用户进程空间后执行事先指定好的函数。
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值