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模型时才回来看。

正如本节我们所给出的所有例子所述,一个输入操作一般有两个不同的阶段:

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

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

阻塞I/O模型

最流行的I/O模型是阻塞I/O模型,本书中到目前为止的所有例子都使用此模型。缺省时,所有套接口都是阻塞的。以数据报套接口作为例子,我们有示例图6.1中的情形。

此例中,我们用UDP而不是TCP,因为对于UDP来说,数据准备好的概念要简单些:整个数据报是否已接收,而对于TCP则要复杂得多,需考虑诸如套接口的低潮限度(lowwater mark)这样的许多附加变量。

在本节的例子中,我们将行数recvfrom视为系统调用,因为我们正考虑应用进程与内核的区别。不论函数recvfrom如何实现(在源自Berkeley的内核中作为系统调用,在系统V内核中作为调用系统调用getmsg的函数)。一般都有一个从一个应用进程中运行到内核中运行的切换,一段时间后再跟一个返回到应用的进程的切换。

图6.1 阻塞I/O模型

在图6.1中,进程调用recvfrom,此系统调用直到数据报到达且拷贝到应用缓冲区或是出错才返回。最常见的错误是系统调用被信号中断,如5.9节所述。我们所说进程阻塞的整段时间是指从调用recvfrom开始到它返回的这段时间,当进程返回成功指示时,应用进程开始处理数据报。

非阻塞I/O模型

当我们把一个套接口设置成非阻塞方式时,即通知内核:当请求的I/O操作非得让进程睡眠不能完成时,不要让进程睡眠,而应返回一个错误。我们将在第15章节详细介绍非阻塞I/O,但为了说明我们所考虑的例子,在图6.2中作一个小结性描述。

前三次调用recvfrom时仍无数据返回,因此内核立即被返回一个 EWOULDBLOCK 错误,第四次调用recvfrom时,数据报已准备好,被拷贝到应用缓冲区,recvfrom返回成功指示,接着就是我们处理数据。

当一个应用进程像这样对一个非阻塞描述字循环调用recvfrom时,我们称此过程为轮询(polling)。应用进程连续不断地查询内核,看看某操作是否准备好,这对CPU时间是极大的浪费,但这种模式指示偶尔才遇到,一般只是专门提供某种功能的系统中才有。

图6.2 非阻塞I/O模型

I/O复用模型

有了I/O复用,我们就可以调用select或poll,在这两个系统调用中的某一个上阻塞,而不是阻塞于真正的I/O系统调用。图6.3是I/O复用模型的一个小结。

我们阻塞于select调用,等待数据报套接口可读。当select返回套接口可读条件时,我们调用recvfrom将数据报拷贝到应用缓冲区中。

将图6.3与图6.1进行比较,似乎没有显示什么优越性,实际上,因使用了系统调用select,要求两次系统调用不是一次,好像变得还有点差。但是,在本章的后面我们将看到,使用select的好处在于我们可以等待多个描述字准备好。

图6.3 I/O复用模型

信号驱动I/O模型

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

图6.4 信号驱动I/O模型

首先,我们允许套接口进行信号驱动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给出一个例子。

图6.5 异步I/O模型

我们调用函数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模型处理的两个阶段都不用于前四个模型。

图6.6 五个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的定义相匹配。

原图

转载于:https://www.cnblogs.com/irockcode/p/8125965.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 《Unix网络编程 1:套接字联网API(第三)》是由W.Richard Stevens和Bill Fenner合著的一本经典计算机网络编程图书。该书以Unix为操作系统平台,深入介绍了网络编程领域的各种概念、技术和实践。本书第三在前两的基础上进行了全面更新和增补,更加符合现代网络编程的需求。 该书主要内容包括了Unix套接字编程、基本I/O函数、地址转换、套接字选项及协议独立性、基本UDP套接字编程、IPv6套接字编程、高级I/O函数、套接字的精确控制、Unix网络IPC、套接字选项(内外带外)以及多路复用。通过阅读该书,读者能够全面了解和掌握Unix网络编程的各个方面。 《Unix网络编程 1:套接字联网API(第三)》以其全面详尽的内容、系统化的知识结构被广大计算机网络编程从业者、学生和研究者所称赞。这本书通过清晰明了的语言,配以丰富的例子和实践案例,使读者能够逐步理解并掌握网络编程领域的基础知识与实用技巧。无论是对于初学者来说,还是对于有一定网络编程基础的人士来说,本书都是一本非常有实用价值的指南。 总之,《Unix网络编程 1:套接字联网API(第三)》是一本经典而全面的计算机网络编程图书,它涵盖了广泛的主题,帮助读者理解和掌握Unix网络编程的各个方面。无论是对于从事网络编程的专业人士,还是对于对网络编程感兴趣的读者来说,这本书都是一本不可或缺的参考书。 ### 回答2: 《UNIX网络编程1:套接字联网API(第3)》是由W.Richard Stevens与Bill Fenner合著的一本经典的UNIX网络编程教材。这本书是学习使用UNIX套接字API进行网络编程的权威指南。 第三的这本书是对前两的全面更新和扩展,增加了许多新特性和最新的网络技术。它以清晰详细的文字和丰富的示例代码,深入浅出地介绍了套接字的使用,包括地址结构、套接字选项、I/O模型、多进程并发编程、进程间通信等方面的知识。 该书的结构十分有序,分为25个节,以便于读者系统地学习和理解。每一节都以实际应用场景和实际问题为例,通过实例向读者解释和演示套接字编程的各个方面。此外,书中还包含了大量的示例代码供读者实践和参考,加深对知识点的理解。 这本书适合那些希望深入学习UNIX套接字编程的开发人员和网络工程师。无论是在UNIX系统下进行C/S架构的网络应用开发,还是进行底层网络协议的研究和开发,都会从该书中获益匪浅。另外,该书也适合作为高校计算机相关专业的教材,供教师和学生参考和学习。 总而言之,《UNIX网络编程1:套接字联网API(第3)》是一本经典且实用的UNIX网络编程教材,深入浅出地介绍了套接字编程的各个方面,对于想深入学习和应用UNIX网络编程的人士来说,是一本不可多得的参考资料。 ### 回答3: 《UNIX网络编程1第三》是一本经典的计算机网络编程参考书籍,由W. Richard Stevens所著。这本书给出了关于UNIX网络编程的详细介绍和实践经验,是学习和理解UNIX网络编程的重要资料。 《UNIX网络编程1第三》的PDF本是该书的电子,可以免费获取。通过PDF格式的书籍,读者可以在电子设备上阅读书籍内容,方便快捷。通过搜索引擎,我们可以找到相应的下载链接,然后可以将其下载到电脑或其他阅读设备上进行学习。 这本书的内容包括了UNIX网络编程的基本概念、网络编程API的使用、套接字编程、高级I/O函数、名字与地址转换、UNIX域协议、IP本4和本6的网络编程等重要主题。书中详细介绍了这些主题的理论知识,并通过大量的示例代码和实践经验展示了如何应用这些知识进行网络编程。 《UNIX网络编程1第三》PDF的免费获取使得这本书变得更加易于获取和传播,方便了广大读者学习和使用UNIX网络编程。无论是初学者还是有一定经验的开发者,都可以通过这本书来提升自己在网络编程领域的技能。读者可以通过系统学习和实践,逐步理解和掌握UNIX网络编程的核心概念和技术,为自己的职业发展打下良好的基础。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值