I/O复用——几种I/O模型对比

I/O复用——几种I/O模型对比

之前在服务器进程终止中讨论的情形,TCP客户端同时要处理两个输入,一是标准输入,二是TCP套接口。而此时若是服务器进程被杀死,服务器尽管正确地给客户发送了FIN分节,但是由于此时客户正阻塞于标准输入fgets(),直到读完一行用户输入(也许此时TCP服务器已经死透了),才能看到那个文件结束符。

I/O复用

因此,我们需要一个能力,对于上面两个I/O,只要有一个或多个I/O条件满足,都应该正确地通知到,这个能力被称为I/O复用,由函数selectpoll支持。

I/O复用的典型应用场景

针对网络应用场景,有以下情形,

  1. 上面讨论过的客户同时处理多个描述字时(一般是交互式输入和网络套接口),此时必须使用I/O复用。
  2. 一个TCP客户同时处理多个套接口。
  3. 一个TCP服务器同时处理监听套接口和已连接套接口。
  4. 一个服务器同时处理TCP和UDP。
  5. 一个服务器同时处理多个服务或者多个协议。

I/O复用并非只限于网络编程,许多其他应用也大范围使用这个能力。

I/O模型概述

首先来看一下Unix下我们可用的五个I/O模型:

  1. 阻塞I/O
  2. 非阻塞I/O
  3. I/O复用
  4. 信号驱动I/O(SIGIO
  5. 异步I/O

一个输入操作一般有两个不同的阶段:

  1. 等待数据准备好。
  2. 从内核到进程拷贝数据。

对于套接口上的输入操作,上述步骤具体是:

  1. 等待数据到达网络,分组到达时,拷贝其到内核缓冲区。
  2. 将数据从内核缓冲区拷贝至应用缓冲区。

阻塞I/O模型

缺省时,所有套接口都是阻塞的。《Unix网络编程》一书中,前五章的所有例子都使用阻塞I/O模型。

为了阐述简单,这里以UDP套接口作为例子,将函数recvfrom视为系统调用,它会有从应用进程中运行和内核中运行的相互切换。

阻塞I/O模型

进程调用recvfrom,此系统调用直到数据报到达且拷贝到应用缓冲区或是出错才返回。此过程可能出现的错误是系统调用被信号中断。我们说的进程阻塞,指的是从进程调用recvfrom开始到它返回的这段时间,当进程返回成功提示时,应用进程开始处理数据报。

非阻塞I/O模型

如果一个套接口被设置成非阻塞模式时,上面说的数据报没有准备好时,进程不会睡眠,而是由内核返回一个错误。

仍讨论之前说的UDP数据报例子:

  1. 数据报没有准备好的时候,调用函数recvfrom,内核立即返回一个EWOULDBLOCK错误。
  2. 数据报准备好的时候,调用函数recvfrom,数据报从内核拷贝到应用缓冲区,recvfrom返回成功提示,进程紧接着会处理数据。

轮询

当一个应用进程对一个非阻塞描述字巡回调用recvfrom时,我们称此过程为轮询(polling)。应用进程连续不断地查询内核,数据是否准备好,这对CPU时间是极大的浪费。

非阻塞I/O模型

I/O复用模型

在I/O复用模型下,我们不再阻塞于真正的I/O系统调用recvfrom,而是在selectpoll这两个系统调用之一阻塞。

例如,阻塞于select调用,等待数据报套接口(可以是多个中任意一个)可读,函数返回对应标识,此时便可调用recvfrom将数据报拷贝到应用缓冲区中。

I/O复用模型

尽管多了一次系统调用,但是select函数可以等待多个套接口描述字这一点,是使用I/O复用模型的一大理由。

信号驱动I/O模型

之前讨论过,内核可以产生信号,进程可以调用sigaction安装一个信号处理函数。这个模型的思路是,数据报准备号以后发送一个信号给进程,信号处理函数收到信号后,调用recvfrom,进行后续的拷贝和处理。

这一模型的好处是,任意一个系统调用都是非阻塞的,主循环可以继续进行,直到数据报准备好的信号到达。

信号驱动I/O模型

异步I/O模型

异步I/O模型中,不再调用函数recvfrom,而是调用函数aio_read,给内核传递描述字,缓冲区指针,缓冲区大小,文件偏移,并告诉内核当整个操作完成时如何通知。此调用立即返回,进程不必阻塞等待I/O操作完成。

这里内核在操作完成时也会产生一个信号,与信号驱动I/O模型不同,这个信号要在数据由内核拷贝到应用缓冲区才产生。

异步I/O模型

五种I/O模型的比较

除了真正的异步I/O模型以外,其他几种模型,最后一阶段的处理都是相同的——阻塞于recvfrom调用,将数据从内核拷贝到应用缓冲区。

五个I/O模型的比较

原创声明,本文系作者授权云+社区发表,未经许可,不得转载。

如有侵权,请联系 yunjia_community@tencent.com 删除。

编辑于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏云计算认知升级

【腾讯云的1001种玩法】 十分钟轻松搞定云架构 · 负载均衡的几种均衡模式

视频内容 [fyckc.jpeg] 今天,我们来学习一下负载均衡的几种均衡模式。通过了解负载均衡的均衡模式,我们可以更好的利用负载均衡来为我们的应用服务。 ...

6086
来自专栏CreateAMind

ls-gan bedroom数据集 pretrain model 和代码

pretrain model 和代码 https://pan.baidu.com/s/1dFbzjlZ pretrain 下载

1082
来自专栏小白安全

安全扫描器Nmap渗透使用教程

介绍 nmap是用来探测计算机网络上的主机和服务的一种安全扫描器。为了绘制网络拓扑图Nmap的发送特制的数据包到目标主机然后对返回数据包进行分析。Nm...

4564
来自专栏磨磨谈

Ceph部署的时候修改默认权重

部署集群的时候权重是默认生成的,这个是根据磁盘大小分配的,我们有的时候需要去修改一下这个默认权重

621
来自专栏我和PYTHON有个约会

爬虫正传-江湖路远-0105-谁的刀快谁就有理

在web操作领域,为了减轻响应数据的体积和保证数据完整性的考虑,可以在浏览器允许的情况下,将数据压缩返回,压缩操作方式目前一般支持主流的两重操作方式[Accep...

702
来自专栏pangguoming

Centos后台运行jar

1562
来自专栏DannyHoo的专栏

记录用户的登录状态

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u010105969/article/details/...

1712
来自专栏Hongten

python开发_platform_获取操作系统详细信息工具

=======================================================

1022
来自专栏我的博客

Nginx搭建负载均衡

Nginx负载均衡的分发方式有4种: 1.轮询,默认采取此方式,Nginx会按照请求时间的先后顺序进行轮询分发,若某台Web Server宕机,Nginx自动将...

3735
来自专栏Python小屋

Python批量Excel文件数据导入SQLite数据库的优化方案

说明:1)需要安装扩展库openpyxl;2)随着数据库的增大,导入速度可能会有所下降;3)本文只考虑Python代码优化,没有涉及数据库的优化;4)本文要点在...

4447

扫码关注云+社区

领取腾讯云代金券