unix网络编程第2版(卷1)_第6章_同步_异步
第6章 I/O复用:select和poll函数
6.1概述
在5.12节中,我们看到TCP客户同时处理两个输入:标准输入和TCP套接口。我们遇到的问题是客户阻塞于(标准输入上的)fgets调用,而服务器进程又被杀死。服务器TCP虽正确地给客户TCP发了一个FIN,但客户进程正阻塞于从标准输入读入,它直到从套接口读时才能看到此文件结束符(可能已经过了很长时间)。我们需要这样的能力:如果一个或多个I/O条件满足(例如,输入已准备好被读,或者描述字可以承接更多的输出)时,我们就被通知到。这个能力被称为I/O复用,是由函数select和poll支持的,我们也对较新的Posix.lg的变种(称为pselect)作介绍。
I/O复用典型地用在下列网络应用场合:
- 当客户处理多个描述字时(一般是交互式输入和网络套接口),必须使用I/O复用,这在前一段中已做了描述。
- 一个客户同时处理多个套接口是可能的,但很少出现。在15.5节一个Web客户的上下文中,我们给出使用select的例子。
- 如果一个TCP服务器既要处理监听套接口,又要处理已连接套接口,一般也要用到I/O复用,如6.8节所述。
- 如果一个服务器既要处理TCP,又要处理UDP,一般也要使用I/O复用,8.15节中我们也要给出这样一个例子。
- 如果一个服务器要处理多个服务或者多个协议(例如,我们将在12.5节描述的inetd守护进程),一般要使用I/O复用。
I/O复用并非只限于网络编程,许多正式应用程序也需要使用这项技术。
6.2 I/O模型
在介绍函数select和poll之前,我们需要回过头来看看
- 阻塞 I/O
- 非阻塞 I/O
- I/O 复用(select和poll)
- 信号驱动 I/O(SIGIO)
- 异步 I/O(Posix.1 的 aio_系列函数)
你在第一次阅读时,可能想略读到本节,到后面的章节中详细介绍不同的I/O模型时才回来看。
正如本节我们所给出的所有例子所述,一个输入操作一般有两个不同的阶段:
- 等待数据准备好。
- 从内核到进程拷贝数据。
对于一个套接口上的输入操作,第一步一般是等待数据到达网络,当分组到达时,它被拷贝到内核中的某个缓冲区,第二步是将数据从内核缓冲区拷贝到应用缓冲区。
阻塞I/O模型
最流行的I/O模型是阻塞I/O模型,本书中到目前为止的所有例子都使用此模型。缺省时,所有套接口都是阻塞的。以数据报套接口作为例子,我们有示例图6.1中的情形。
此例中,我们用UDP而不是TCP,因为对于UDP来说,数据准备好的概念要简单些:整个数据报是否已接收,而对于TCP则要复杂得多,需考虑诸如套接口的低潮限度(lowwater mark)这样的许多附加变量。
在本节的例子中,我们将行数recvfrom视为系统调用,因为我们正考虑应用进程与内核的区别。不论函数recvfrom如何实现(在源自Berkeley的内核中作为系统调用,在系统V内核中作为调用系统调用getmsg的函数)。一般都有一个从一个应用进程中运行到内核中运行的切换,一段时间后再跟一个返回到应用的进程的切换。

在图6.1中,进程调用recvfrom,此系统调用直到数据报到达且拷贝到应用缓冲区或是出错才返回。最常见的错误是系统调用被信号中断,如5.9节所述。我们所说进程阻塞的整段时间是指从调用recvfrom开始到它返回的这段时间,当进程返回成功指示时,应用进程开始处理数据报。
非阻塞I/O模型
当我们把一个套接口设置成非阻塞方式时,即通知内核:当请求的I/O操作非得让进程睡眠不能完成时,不要让进程睡眠,而应返回一个错误。我们将在第15章节详细介绍非阻塞I/O,但为了说明我们所考虑的例子,在图6.2中作一个小结性描述。
前三次调用recvfrom时仍无数据返回,因此内核立即被返回一个 EWOULDBLOCK 错误,第四次调用recvfrom时,数据报已准备好,被拷贝到应用缓冲区,recvfrom返回成功指示,接着就是我们处理数据。
当一个应用进程像这样对一个非阻塞描述字循环调用recvfrom时,我们称此过程为轮询(polling)。应用进程连续不断地查询内核,看看某操作是否准备好,这对CPU时间是极大的浪费,但这种模式指示偶尔才遇到,一般只是专门提供某种功能的系统中才有。

I/O复用模型
有了I/O复用,我们就可以调用select或poll,在这两个系统调用中的某一个上阻塞,而不是阻塞于真正的I/O系统调用。图6.3是I/O复用模型的一个小结。
我们阻塞于select调用,等待数据报套接口可读。当select返回套接口可读条件时,我们调用recvfrom将数据报拷贝到应用缓冲区中。
将图6.3与图6.1进行比较,似乎没有显示什么优越性,实际上,因使用了系统调用select,要求两次系统调用不是一次,好像变得还有点差。但是,在本章的后面我们将看到,使用select的好处在于我们可以等待多个描述字准备好。

信号驱动I/O模型
我们也可以用信号,让内核在描述字准备好时用信号SIGIO通知我们,我们将此方法称为信号驱动I/O,图6.4对此作了一个小结。

首先,我们允许套接口进行信号驱动I/O(我们将在22.2节对此进行讨论),并通过系统调用sigaction安装一个信号处理程序。此系统调用立即返回,进程继续工作,它是非阻塞的。当数据报准备好被读时,就为该进程生成一个SIGIO信号。我们随即可以在信号处理程序中调用recvfrom来读数据报,并通知主循环数据已准备好被处理(这正是我们在22.3节中所要做的事情)。也可以通知主循环,让它来读取数据报。
无论我们如何处理SIGIO信号,这种模式的好处是当等待数据报到达时,可以不阻塞。主循环可以继续执行,只是等待信号处理程序的通知;或者数据已准备好被处理,或者数据报已准备好被读。
异步I/O模型
异步I/O是Posix.1的1993版本中的新内容("实时"扩展)。我们让内核启动操作,并在整个操作完成后(包括数据从内核拷贝到我们自己的缓冲区)通知我们。因为这种模型还没有广泛使用,本书不做讨论。这种模型与前一节介绍的信号驱动模型的主要区别在于:信号驱动I/O是由内核通知我们何时可以启动一个I/O操作,而异步是由内核通知我们I/O操作何时完成。图6.5给出一个例子。

我们调用函数aio_read(Posix 异步I/O函数以 aio_ 或 lio_ 开头),给内核传递描述字,缓冲区指针、缓冲区大小(与read相同的三个参数)、文件偏移(与lseek类似),并告诉内核当整个操作完成时如何通知我们。此系统调用立即返回,我们的进程不阻塞与等待I/O操作的完成。在此例子中,我们假设要求内核在操作完成时生成一个信号,此信号知道数据已拷贝到应用缓冲区才产生,这一点是与信号驱动I/O模型不同的。
正如本书说述,很少有系统支持Posix.1的异步I/O模型。例如,我们还不能确定系统是否支持套接口上的这种模型。这儿我们用它,只是作为一个与信号驱动I/O模型进行比较的例子。
各种I/O模型的比较
图6.6示出了上述五种不同I/O模型的比较。它表明:前四种模型的主要区别都在第一阶段,因为前四种魔性的第二阶段基本相同:在数据从内核拷贝到调用者的缓冲区时,进程阻塞于recvfrom调用。然后,异步I/O模型处理的两个阶段都不用于前四个模型。

同步I/O与异步I/O
Posix.1定义这两个术语如下:
- 同步I/O操作引起请求进程阻塞,知道I/O操作完成。
- 异步I/O操作不引起请求进程阻塞。
根据上述定义,我们的前四个模型————阻塞I/O模型、I/O复用模型和信号驱动I/O模型都是同步I/O模型,因为真正的I/O操作(recvfrom)阻塞进程,只有异步I/O模型与此异步I/O的定义相匹配。

unix网络编程第2版(卷1)_第6章_同步_异步的更多相关文章
- 【unix网络编程第三版】阅读笔记(五):I/O复用:select和poll函数
本博文主要针对UNP一书中的第六章内容来聊聊I/O复用技术以及其在网络编程中的实现 1. I/O复用技术 I/O多路复用是指内核一旦发现进程指定的一个或者多个I/O条件准备就绪,它就通知该进程.I/O ...
- 【unix网络编程第三版】阅读笔记(三):基本套接字编程
unp第三章主要介绍了基本套接字编程函数.主要有:socket(),bind(),connect(),accept(),listen()等. 本博文也直接进入正题,对这几个函数进行剖析和讲解. 1. ...
- 【UNIX网络编程第三版】阅读笔记(一):代码环境搭建
粗略的阅读过<TCP/IP详解>和<计算机网络(第五版)>后,开始啃这本<UNIX网络编程卷一:套接字联网API>,目前linux下的编程不算太了解,在阅读的过程中 ...
- 【unix网络编程第三版】ubuntu端口占用问题
<unix网络编程>一书中的代码并不是能直接运行,有时候需要结合各方面的知识来解决,大家在这本书的时候,一定要把代码都跑通,不难你会错过很多学习的机会! 1.问题描述 本人在阅读<U ...
- 【unix网络编程第三版】阅读笔记(二):套接字编程简介
unp第二章主要将了TCP和UDP的简介,这些在<TCP/IP详解>和<计算机网络>等书中有很多细致的讲解,可以参考本人的这篇博客[计算机网络 第五版]阅读笔记之五:运输层,这 ...
- 《UNIX网络编程(第3版)》unp.h等源码文件的编译安装
操作系统:Mac OS X 10.11.5 1.下载书中的源代码:点击下载 2.切换到解压后的目录 unpv13e,先查看下 README,依次执行: ./configure cd lib make ...
- 【unix网络编程第三版】阅读笔记(四):TCP客户/服务器实例
本篇博客主要记录一个完整的TCP客户/服务器实例的编写,以及从这个实例中引发的对僵死进程的处理等问题. 1. TCP客户/服务器功能需求 本实例完成以下功能: (1) 客户从标准输入读入一行文本,并写 ...
- UNIX 网络编程第三版
第五章p102: ps -t pts/6 -o pid,ppid,tty,stat,args,wchan 在我的系统上运行时出现:TTY not found linux发行版为mint17.1 改用 ...
- Unix网络编程第三版源码编译
配置: $ cd Unix-Network-Programming/ $ chmod 755 configure $ ./configure 主要的工作是检查系统是否有源码编译所依赖的各种资源(系统版 ...
随机推荐
- 解决打开png图片黑屏问题(批量还原Xcode优化后的png)
window 打开Xcode 里面的png图片会黑屏,但是在mac 打开就显示正常, 这是因为Xocde里面的png图片被 pngcrush 优化过了,需要还原它的优化,window 平台才可以打开. ...
- Springboot(一):使用Intellij中的Spring Initializr来快速构建Spring Boot工程
使用Intellij中的Spring Initializr来快速构建Spring Boot工程 New---Project 可以看到图所示的创建功能窗口.其中Initial Service Url指向 ...
- [整]swp文件的处理
报错 vim非正常关闭,再下次编辑打开文件时均为显示如下警告信息: Swap file "test.xml.swp" already exists! [O]pen Read-Onl ...
- linux 安装MySql 5.7.21 操作步骤
一:到mysql官网下载最新的mysql包 mysql-5.7.21-linux-glibc2.12-x86_64 https://dev.mysql.com/downloads/mysql/ 二:在 ...
- Flask-SQLAlchemy.........>model创建表
import datetime from sqlalchemy import create_engine from sqlalchemy.ext.declarative import declarat ...
- AbstractQueuedSynchronizer的简单分析
说明:本作者是文章的原创作者,转载请注明出处:本文地址:http://www.cnblogs.com/qm-article/p/7955781.html 一.AbstractQueuedSynchro ...
- oracle erp 表结构
BOM模块常用表结构 表名: bom.bom_bill_of_materials 说明: BOM清单父项目 BILL_SEQUENCE_ID NUMBER 清单序号(关键字)ASSEMBLY_ITEM ...
- 【JAVA】SWING_ 界面风格
在java中,界面外观的管理是由UIManager类来管理的.不同的系统上安装的外观不一样 ,默认的是java的跨平台外观. 1.获取系统所有外观 import javax.swing.*; impo ...
- 人生苦短,我用Python 第一篇
一.变量名 自定义变量名只能用 数字.字母.下划线组成. 使用变量前,需对其先赋值 注意:1.变量名不能以数字开头: 2.不能是关键字:例如:'and', 'as', 'assert', ' ...
- python来写打飞机
准备用python写一个打飞机的游戏,相信能够写完这个项目,我对python的学习应该也算可以了. 首先,我们要使用python的一个pygame的库来写,这个库的安装比较简单就是普通的pip安装就可 ...