文档章节

UNIX系统的IO模型

学良
 学良
发布于 2013/09/06 06:45
字数 1894
阅读 810
收藏 21

其实并非原创,只是摘录了Stevens的大作《UNIX网络编程》,写下来,一、加深理解和记忆;二、书是借的,记录一下备忘。感谢臻,借我此书一阅,受益匪浅。 

6.2 I/O模型

阻塞式I/O

非阻塞式I/O

I/O复用;

信号驱动式I/O

异步I/O

一个输入操作通常包括两个不同的阶段:

1) 等待数据准备好;

2) 从内核向进程复制数据;

对于一个套接字上的输入操作,第一步通常涉及等待数据从网络中到达。当所等待分组到达时,它被复制到内核中的某个缓冲区。第二步就是把数据从内核缓冲区复制到应用进程缓冲区。

6.2.1 阻塞式I/O模型

最流行的I/O模型是阻塞式I/Oblocking I/O)模型,默认情况下,所有套接字都是阻塞的。以数据报套接字作为例子,我们有如图6-1所示的情形。

6-1 阻塞式I/O模型

在图6-1中,进程调用recvfrom,其系统调用直到数据报到达且被复制到应用进程的缓冲区中或者发生错误才返回。我们说进程在从调用recvfrom开始到它返回的整段时间内是被阻塞的。recvfrom成功返回后,应用进程开始处理数据报。

6.2.2 非阻塞式I/O模型

进程把一个套接字设置成非阻塞是在通知内核:当所请求的I/O操作非得把本进程投入睡眠才能完成时,不要把本进程投入睡眠,而是返回一个错误。非阻塞式I/O(notblocking I/O)模型如图6-2所示:

 

6-2 非阻塞式I/O模型

前三次调用recvfrom时没有数据可返回,因此内核转而立即返回一个EWOULDBLOCK错误。第四次调用recvfrom时已有一个数据报准备好,它被复制到应用进程缓冲区,于是recvfrom成功返回。我们接着处理数据。

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

6.2.3 I/O复用模型

有了I/O复用(I/O multiplexing),我们就可以调用selectpoll,阻塞在这两个系统调用中的某一个上,而不是阻塞在真正的I/O系统调用上。图6-3概括展示了I/O复用模型。

 

6-3 I/O复用模型

我们阻塞于select调用,等待数据报套接字变为可读。当select返回套接字可读这一条件时,我们调用recvfrom把所读数据报复制到应用进程缓冲区。

比较图6-3和图6-1I/O复用并不显得有什么优势,事实上由于使用select需要两个而不是单个系统调用,I/O复用还稍有劣势。使用select的优势在于我们可以等待多个描述符就绪。

I/O复用密切相关的另一种I/O模型是在多线程中使用阻塞式I/O(我们经常这么干)。这种模型与上述模型极为相似,但它并没有使用select阻塞在多个文件描述符上,而是使用多个线程(每个文件描述符一个线程),这样每个线程都可以自由的调用recvfrom之类的阻塞式I/O系统调用了。

6.2.4 信号驱动式I/O模型

我们也可以用信号,让内核在描述符就绪时发送SIGIO信号通知我们。我们称这种模型为信号驱动式I/O(signal-driven I/O),图6-4是它的概要展示。 

 

6-4 信号驱动式I/O模型

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

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

6.2.5 异步I/O模型

异步I/Oasynchronous I/O)由POSIX规范定义。演变成当前POSIX规范的各种早起标准所定义的实时函数中存在的差异已经取得一致。一般地说,这些函数的工作机制是:告知内核启动某个操作,并让内核在整个操作(包括将数据从内核复制到我们自己的缓冲区)完成后通知我们。这种模型与前一节介绍的信号驱动模型的主要区别在于:信号驱动式I/O是由内核通知我们何时可以启动一个I/O操作,而异步I/O模型是由内核通知我们I/O操作何时完成。图6-5给出了一个例子。

 

6-5 异步I/O模型

我们调用aio_read函数(POSIX异步I/O函数以aio_lio_开头),给内核传递描述符、缓冲区指针、缓冲区大小(与read相同的三个参数)和文件偏移(与lseek类似),并告诉内核当整个操作完成时如何通知我们。该系统调用立即返回,并且在等待I/O完成期间,我们的进程不被阻塞。本例子中我们假设要求内核在操作完成时产生某个信号。改信号直到数据已复制到应用进程缓冲区才产生,这一点不同于信号驱动I/O模型。

6.2.6 各种I/O模型的比较

6-6对比了上述5中不同的I/O模型。可以看出,前4中模型的主要区别在于第一阶段,因为他们的第二阶段是一样的:在数据从内核复制到调用者的缓冲区期间,进程阻塞于recvfrom调用。相反,异步I/O模型在这两个阶段都要处理,从而不同于其他4中模型。

 

 

6-6 5I/O模型的比较

6.2.7 同步I/O和异步I/O对比

POSIX把这两个术语定于如下:

同步I/O操作(sysnchronous I/O opetation)导致请求进程阻塞,直到I/O操作完成;

异步I/O操作(asynchronous I/O opetation)不导致请求进程阻塞。

根据上述定义,我们的前4种模型----阻塞式I/O模型、非阻塞式I/O模型、I/O复用模型和信号驱动I/O模型都是同步I/O模型,因为其中真正的I/O操作(recvfrom)将阻塞进程。只有异步I/O模型与POSIX定义的异步I/O相匹配。

© 著作权归作者所有

共有 人打赏支持
学良
粉丝 15
博文 5
码字总数 5949
作品 0
杭州
程序员
加载中

评论(1)

曾经的十字镐
曾经的十字镐
非常好
Unix 网络 IO 模型: 同步异步, 傻傻分不清楚?

出处 阻塞 IO, 非阻塞 IO, 同步 IO, 异步 IO 这些术语相信有不少朋友都也不同程度的困惑吧? 我原来也是, 什么同步非阻塞 IO, 异步非阻塞 IO 的, 搞的头都大了. 后来仔细读了一遍 《UNIX 网络...

永顺
2017/11/29
0
0
关于IO的同步,异步,阻塞,非阻塞

上次写了一篇文章:Unix IO 模型学习。恰巧在这次周会的时候,@fp1203 (goldendoc成员之一) 正好在讲解poll和epoll的底层实现。中途正好讨论了网络IO的同步、异步、阻塞、非阻塞的概念,当时...

大数据之路
2012/10/08
0
0
突然发现到今天已经很难找到对底层理解这么透彻的人

链接: http://blog.csdn.net/elssann/archive/2004/10/25/150088.aspx 原文: 在VC版的网络编程区,基本上每天都可以看到大量关于IOCP(完成端口)的帖子和讨论,很多人比较反感IOCP,特别是...

刘小兵2014
2010/12/07
0
0
IO复用\阻塞IO\非阻塞IO\同步IO\异步IO

本文是对《UNIX网络编程卷1》第6章的总结。 一、 什么是IO复用? 它是内核提供的一种同时监控多个文件描述符状态改变的一种能力;例如当进程需要操作多个IO相关描述符时(例如服务器程序要同...

商者
2016/04/06
39
0
阻塞,非阻塞IO和同步,异步IO

在看ACE的过程中,难免对socket的一些特别的api有点质疑,于是不得不求助于unix网络编程,在看的过程中 终于懂得了阻塞,非阻塞和同步,异步的区别,以前认为非阻塞就是一中异步模式呢,哎,...

shawn chen
2010/12/24
0
2

没有更多内容

加载失败,请刷新页面

加载更多

下一页

java大数据转换16进制转10进制

public static void main(String[] args) {String hex = "0xdbf3accc683297cf0000";BigInteger amount = new BigInteger(hex.substring(2), 16);System.out.println(amount);......

任梁荣
昨天
1
0
OSChina 周六乱弹 —— 目测我们程序员丁克的几率不大

Osc乱弹歌单(2018)请戳(这里) 【今日歌曲】 @真Skr小机灵鬼儿:8.13分享Jocelyn Pook/Russian Red的单曲《Loving Strangers》 《Loving Strangers》- Jocelyn Pook/Russian Red 手机党少...

小小编辑
昨天
9
3
TypeScript基础入门 - 函数 - 剩余参数

转载 TypeScript基础入门 - 函数 - 剩余参数 项目实践仓库 https://github.com/durban89/typescript_demo.gittag: 1.2.1 为了保证后面的学习演示需要安装下ts-node,这样后面的每个操作都能...

durban
昨天
1
0
OpenCV边缘检测算子原理总结及实现

1. 拉普拉斯算子 原理:是一种基于图像导数运算的高通线性滤波器。它通过二阶导数来度量图像函数的曲率。 拉普拉斯算子是最简单的各向同性微分算子,它具有旋转不变性。一个二维图像函数的拉...

漫步当下
昨天
0
0
Spring源码阅读——1

开始读Spring源码吧,看再多的技术博客,不如自己看一下~~~~~ Spring源码目前在github中,新版本基于gradle构建。所以阅读源码需要先安装github和gradle。 spring中git地址 1、安装git(略)...

叶枫啦啦
昨天
1
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部