I/O模型

UNIX下可用的5种I/O模型:

(1)阻塞I/O

(2)非阻塞I/O

(3)I/O复用(select和poll)

(4)信号驱动I/O(SIGIO)

(5)异步I/O

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

1、阻塞I/O模型

最流行的I/O模型是阻塞I/O(blocking I/O)模型。缺省情况下,所有套接口都是阻塞的。

以数据报套接口作为例子,我们有下图所示的情形:

进程调用recvfrom,其系统调用直到数据报到达且被拷贝到应用进程的缓冲区中或者发生错误才返回。最常见的错误是系统调用被信号中断。我们说进程在从调用recvfrom开始到它返回的整段时间内是被阻塞的。recvfrom成功返回后,应用进程开始处理数据。

2、非阻塞I/O模型

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

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

当一个应用进程像这样对一个非阻塞描述字循环调用recvfrom时,我们称之为轮询(polling)。应用进程持续轮询内核,以查看某个操作是否就绪。这么做往往耗费大量CPU时间,不过这种模型偶尔也会遇到,通常是在只专门提供某种功能的系统中才有。

3、I/O复用模型

有了I/O复用(I/O multiplexing),我们就可以调用select或poll,阻塞在这两个系统调用中的某一个之上,而不是阻塞在真正的I/O系统调用上。下图展示了I/O复用模型。

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

比较I/O复用模型和阻塞I/O模型,I/O复用并没有显示出什么优势,事实上由于使用select需要使用两个而不是单个系统调用,I/O复用还稍有劣势。使用select的优势在于我们可以等待多个描述字就绪。

与I/O复用密切相关的另一种I/O模型是在多线程中使用阻塞I/O。这种模型与I/O复用模型极为相似,代替使用select阻塞在多个文件描述字上的是,使用多个线程(每个文件描述字一个线程),这样每个线程都可以自由地调用诸如recvfrom之类的阻塞式I/O系统调用了。

4、信号驱动I/O模型

我们也可以用信号,让内核在描述字就绪时发送SIGIO信号通知我们。我们称这种模型为信号驱动I/O(signal-driven I/O),如下图所示:

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

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

5、异步I/O模型

异步I/O(asynchronous I/O)由POSIX规范定义。一般地说,这些函数的工作机制是:告知内核启动某个操作,并让内核在整个操作(包括将数据从内核拷贝到我们自己的缓冲区)完成后通知我们。这种模型与信号驱动模型的主要区别在于:信号驱动I/O是由内核通知我们何时启动一个I/O操作,而异步I/O模型是由内核通知我们I/O操作何时完成。

我们调用aio_read函数(POSIX异步I/O函数以aio_或lio_开头),给内核传递描述字、缓冲区指针、缓冲区大小(与read相同的三个参数)、文件偏移(与lseek类似),并告诉内核当整个操作完成时如何通知我们。该系统调用立即返回,在等待I/O完成期间,我们的进程不被阻塞。

6、各种模型的比较

7、同步I/O和异步I/O

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

  • 同步I/O操作(synchronous I/O operation)导致请求进程阻塞,直到I/O操作完成。
  • 异步I/O操作(asynchronous I/O operation)不导致请求进程阻塞。

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

UNIX网络编程读书笔记:I/O模型(阻塞、非阻塞、I/O复用、信号驱动、异步)的更多相关文章

  1. UNIX网络编程--读书笔记

    会集中这段时间写UNIX网络编程这本书的读书笔记,准备读三本,这一系类的文章会不断更新,一直会持续一个月多,每篇的前半部分是书中讲述的内容,每篇文章的后半部分是自己的心得体会,文章中的红色内容是很重要 ...

  2. UNIX网络编程读书笔记:简介

    认知套接口编程接口 理解原始套接口(raw socket)的概念   值得注意的是,客户和服务器是典型的用户进程,而TCP和IP协议则通常是系统内核协议栈的一部分. 上图中在TCP和UDP之间留有间隙 ...

  3. Unix 网络编程 读书笔记1

    第一章: C/C++语言提供两种不同的编程模式:IPL32和PL64.► IPL32 ● 表示integer/pointer/long三种数据类型是32位(4个字节),在这种模式下,提供32位的地址空 ...

  4. UNIX网络编程读书笔记:原始套接口

    概述 应用程序可以绕过传输层而直接使用IPv4和IPv6,这称为原始套接口(raw socket).http://www.cnblogs.com/nufangrensheng/p/3583435.ht ...

  5. UNIX网络编程读书笔记:套接口选项

    概述 有很多方法来获取和设置影响套接口的选项: getsockopt和setsockopt函数 fcntl函数 ioctl函数 getsockopt和setsockopt函数 这两个函数仅用于套接口. ...

  6. UNIX网络编程读书笔记:select函数

    select函数概况: select函数允许进程指示内核等待多个事件中的任何一个发生,并仅在有一个或多个事件发生或经历一段指定的时间后才唤醒它. 作为一个例子,我们可以调用select,告知内核仅在下 ...

  7. Unix 网络编程 读书笔记2

    第三章 套接字编程简介 每一个 Socket 都用一个半相关描述:{协议,本地地址,本地端口}一个完整的 Socket 则用一个相关描述{协议,本地地址,本地端口,远程地址,远程端口}每一个 Sock ...

  8. UNIX网络编程读书笔记:UNIX域协议

    概述 UNIX域协议并不是一个实际的协议族,而是在单个主机上执行客户/服务器通信的一种方法,所用API与在不同主机上执行客户/服务器通信所用的API(套接口API)相同.UNIX域协议可视为进程间通信 ...

  9. UNIX网络编程读书笔记:基本SCTP套接口编程

    概述 SCTP是一个较新的传输协议,于2000年在IETF得到标准化(TCP是在1981年标准化的).它最初是为满足不断增长的IP电话市场设计的:具体地说,就是穿越因特网传输电话信令. SCTP是一个 ...

随机推荐

  1. A1060. Are They Equal

    If a machine can save only 3 significant digits, the float numbers 12300 and 12358.9 are considered ...

  2. 我们一起来详细的了解react的语法以及组件的使用方法

    jsx的介绍 React 使用 JSX 来替代常规的 JavaScript. JSX 是一个看起来很像 XML 的 JavaScript 语法扩展. jsx的优点 JSX 执行更快,因为它在编译为 J ...

  3. 错误:分析 EntityName 时出错 web配置

    会发生这种错误的环境:ASP.NET 或 XML情况:一个原本运行正常的C#页面,因为SQL的密码更改后一直出现“分析 EntityName 时出错”错误,验证过web.config的SQL Conn ...

  4. C#使用Ado.Net读写数据库

    1.使用DataReader方式读取资料 [csharp] view plain copy String connString = ConfigurationManager.ConnectionStr ...

  5. django分页功能

    采用django自带的Paginator功能 from django.core.paginator import Paginator food = foodInfo.objects.filter(fo ...

  6. Java_myBatis入门写法

    一.整体步骤 1.读取全局配置文件“SqlMapConfig.xml” 2.用SqlSessionFactoryBuilder来创建一个SqlSessionFactory 3.用创建好的SqlSess ...

  7. Linux命令之rm

    rm命令 用处:删除文件 用法:在终端上输入rm加上要删除的文件的名字(如果有的话,包括后缀) 示例: (我要删除newfile这个文件)

  8. 在ASP.Net环境中,当用户点击报表中的超链接时如何调用Java Script方法?

    问题描述:在ASP.Net环境中,当用户点击报表中的超链接时如何调用Java Script方法? 问题解答: 你可以在TextObject.Hyperlink对象中编写js代码(javascript: ...

  9. luogu 1030 求先序遍历

    此题给出中序遍历和后序遍历后的序列,乍一看确乎想不出法子解决,毕竟是逆向思维: 但是后序遍历的特殊性质 son1,son2,x 使得后序的末尾便是根节点,再由中序天然的递归性质便可递归输出,用下fin ...

  10. Java SE之Java中堆内存和栈内存[转/摘]

    [转/摘]1-3Java中堆内存和栈内存 注解:内存(Memory)即 内存储器,主存,其作用是用于暂时存放CPU中的运算数据,以及与硬盘等外部存储器(辅存)交换的数据. Java中把内存分为两种:栈 ...