- 浏览: 141090 次
文章分类
最新评论
Unix 下有 5 种可用的 I/O 模型:阻塞式 I/O、非阻塞式 I/O、I/O 复用(select 和 poll)、信号驱动式 I/O(SIGIO)和 异步 I/O(POSIX 的 aio_ 系列函数)。其中的每种模型细节会在后面陆续补上,本节只对它们进行大概的描述。
一个输入操作通常包括两个不同的阶段:
(1)等待数据准备好;
(2)从内核向进程复制数据。对于一个套接字上的输入操作,第一步通常涉及等待数据从网络中到达。当所等待的分组到达时,它就被复制到内核中的某个缓冲区。第二步就是把数据从内核缓冲区复制到应用进程缓冲区。
阻塞式 I/O 模型是最流行的 I/O 模型。所有套接字默认都是阻塞的。为了简单,以数据报套接字为例(下同),阻塞式 I/O 模型上的输入操作情形如下图所示。
进程调用 recvfrom,其系统调用直到数据报到达且被复制到应用进程的缓冲区中或者发生错误才返回。最常见的错误是系统调用被信号中断。我们说进程在从调用 recvfrom 开始到它返回的整段时间内是被阻塞的。recvfrom 成功返回后,应用进程才开始处理数据报。
在非阻塞式 I/O 模型中,进程把一个套接字设置成非阻塞是在通知内核:当所请求的 I/O 操作非得把本进程投入睡眠才能完成时,不要把本进程投入睡眠,而是返回一个错误。其上的输入操作情形如下图。
图中前三次调用 recvfrom 时没有数据可返回,因此内核转而立即返回一个 EWOULDBLOCK 错误。应用进程像这样持续轮询内核以查看某个操作是否就绪,往往会耗费大量 CPU 时间,不过这种模型偶尔也会遇到,通常是在专门提供某一种功能的系统中才有。
有了 I/O 复用(I/O multiplexing),就可以调用 select 或 poll 函数,阻塞在这两个系统调用的某一个之上,而不是阻塞在真正的 I/O 系统调用上。
这里阻塞于 select 调用,当 select 返回套接字可读这一条件时,就调用 recvfrom 把所读的数据报复制到应用进程缓冲区。相比较于阻塞式 I/O,由于使用 select 需要两个系统调用,似乎 I/O 复用还稍有劣势。不过使用 select 的优势在于可以等待多个描述符就绪。与该模型极为相似的另一种 I/O 模型是在多线程中使用阻塞式 I/O,但它没有使用 select 阻塞在多个文件描述符上,而是使用多个线程(每个文件描述符一个线程),这样每个线程都可以自由地调用诸如 recvfrom 之类的阻塞式 I/O 系统调用了。
信号驱动式 I/O 就是让内核在描述符就绪时发送 SIGIO 信号通知我们。
首先开启套接字的信号驱动式 I/O 功能,并通过 sigaction 系统调用安装一个信号处理函数,然后系统调用立即返回,进程继续工作。当数据报准备好读取时,内核就为该进程产生一个 SIGIO 信号,随后就可在信号处理函数中调用 recvfrom 读取数据报,并通知主循环数据已准备好待处理,或者立即通知主循环,让它读取数据报。
异步 I/O 模型中的工作机制是:告知内核启动某个操作,并让内核在整个操作(包括将数据从内核复制到缓冲区)完成后再通知我们。这种模型与信号驱动模型的主要区别在于:信号驱动是由内核通知我们何时可以启动一个 I/O 操作,而异步 I/O 模型是由内核通知我们 I/O 操作何时完成。
这里调用 aio_read 函数(POSIX 异步 I/O 函数以 aio_ 或 lio_ 开头)给内核传递描述符、缓冲区指针、缓冲区大小(与 read 相同的三个参数)和文件偏移,并告诉内核当整个操作完成时如何通知我们。该系统调用会立即返回,而且进程在等待 I/O 完成期间不会被阻塞。
这 5 种 I/O 模型的区别如下图所示。
同步 I/O 和异步 I/O 这两个术语在 POSIX 中的定义如下:
* 同步 I/O 操作导致请求进程阻塞,直到 I/O 操作完成。
* 异步 I/O 操作不导致请求进程阻塞。
根据该定义,可见前 4 种 I/O 模型都是同步 I/O 模型,因为其中真正的 I/O 操作会阻塞进程,而只有异步 I/O 模型与 POSIX 定义的异步 I/O 相匹配。
一个输入操作通常包括两个不同的阶段:
(1)等待数据准备好;
(2)从内核向进程复制数据。对于一个套接字上的输入操作,第一步通常涉及等待数据从网络中到达。当所等待的分组到达时,它就被复制到内核中的某个缓冲区。第二步就是把数据从内核缓冲区复制到应用进程缓冲区。
阻塞式 I/O 模型是最流行的 I/O 模型。所有套接字默认都是阻塞的。为了简单,以数据报套接字为例(下同),阻塞式 I/O 模型上的输入操作情形如下图所示。
进程调用 recvfrom,其系统调用直到数据报到达且被复制到应用进程的缓冲区中或者发生错误才返回。最常见的错误是系统调用被信号中断。我们说进程在从调用 recvfrom 开始到它返回的整段时间内是被阻塞的。recvfrom 成功返回后,应用进程才开始处理数据报。
在非阻塞式 I/O 模型中,进程把一个套接字设置成非阻塞是在通知内核:当所请求的 I/O 操作非得把本进程投入睡眠才能完成时,不要把本进程投入睡眠,而是返回一个错误。其上的输入操作情形如下图。
图中前三次调用 recvfrom 时没有数据可返回,因此内核转而立即返回一个 EWOULDBLOCK 错误。应用进程像这样持续轮询内核以查看某个操作是否就绪,往往会耗费大量 CPU 时间,不过这种模型偶尔也会遇到,通常是在专门提供某一种功能的系统中才有。
有了 I/O 复用(I/O multiplexing),就可以调用 select 或 poll 函数,阻塞在这两个系统调用的某一个之上,而不是阻塞在真正的 I/O 系统调用上。
这里阻塞于 select 调用,当 select 返回套接字可读这一条件时,就调用 recvfrom 把所读的数据报复制到应用进程缓冲区。相比较于阻塞式 I/O,由于使用 select 需要两个系统调用,似乎 I/O 复用还稍有劣势。不过使用 select 的优势在于可以等待多个描述符就绪。与该模型极为相似的另一种 I/O 模型是在多线程中使用阻塞式 I/O,但它没有使用 select 阻塞在多个文件描述符上,而是使用多个线程(每个文件描述符一个线程),这样每个线程都可以自由地调用诸如 recvfrom 之类的阻塞式 I/O 系统调用了。
信号驱动式 I/O 就是让内核在描述符就绪时发送 SIGIO 信号通知我们。
首先开启套接字的信号驱动式 I/O 功能,并通过 sigaction 系统调用安装一个信号处理函数,然后系统调用立即返回,进程继续工作。当数据报准备好读取时,内核就为该进程产生一个 SIGIO 信号,随后就可在信号处理函数中调用 recvfrom 读取数据报,并通知主循环数据已准备好待处理,或者立即通知主循环,让它读取数据报。
异步 I/O 模型中的工作机制是:告知内核启动某个操作,并让内核在整个操作(包括将数据从内核复制到缓冲区)完成后再通知我们。这种模型与信号驱动模型的主要区别在于:信号驱动是由内核通知我们何时可以启动一个 I/O 操作,而异步 I/O 模型是由内核通知我们 I/O 操作何时完成。
这里调用 aio_read 函数(POSIX 异步 I/O 函数以 aio_ 或 lio_ 开头)给内核传递描述符、缓冲区指针、缓冲区大小(与 read 相同的三个参数)和文件偏移,并告诉内核当整个操作完成时如何通知我们。该系统调用会立即返回,而且进程在等待 I/O 完成期间不会被阻塞。
这 5 种 I/O 模型的区别如下图所示。
同步 I/O 和异步 I/O 这两个术语在 POSIX 中的定义如下:
* 同步 I/O 操作导致请求进程阻塞,直到 I/O 操作完成。
* 异步 I/O 操作不导致请求进程阻塞。
根据该定义,可见前 4 种 I/O 模型都是同步 I/O 模型,因为其中真正的 I/O 操作会阻塞进程,而只有异步 I/O 模型与 POSIX 定义的异步 I/O 相匹配。
发表评论
-
Unix 域套接字与描述符的传递
2019-03-27 23:59 710在Unix 域套接字概述一节中介绍了什么是 U ... -
Unix 域套接字概述
2019-03-12 22:48 979Unix 域协议并不是一个实际的协议族,而是在 ... -
kqueue 接口
2019-03-06 00:47 691kqueue 接口是 ... -
辅助数据
2019-02-28 00:40 687辅助数据(a ... -
recv/send 和 recvmsg/sendmsg 函数
2019-01-22 00:40 1553recv 和 send ... -
inetd 守护进程介绍
2019-01-09 21:51 1052在 4.3 BSD 系统之前,很多网络服务都是 ... -
主机名与 IP 地址的转换(续)
2018-12-25 00:37 955在主机名与 IP 地址的转换一节中提到的 ge ... -
主机名与 IP 地址的转换
2018-11-14 00:20 2306在网络编程中,尽管大部分情况下操作的都是 IP ... -
SCTP 事件通知
2018-02-08 03:49 984SCTP 提供了多种可用的通知,用户可经由这些通知追踪 ... -
SCTP 套接字选项
2018-02-04 09:35 1691在获取和设置套接 ... -
SCTP 套接字编程基础函数
2018-02-04 10:08 1055SCTP 服务器可以使 ... -
SCTP 套接字编程基础概念
2018-01-18 00:10 561SCTP 套接字分为一到一套接字和一到多套接字。提供一 ... -
UDP套接字编程基础
2018-01-14 10:37 574下图显示了使用 UDP 套接字编写客户/服务器程序时的 ... -
通用套接字选项
2018-01-02 00:46 551在获取和设置套接 ... -
获取和设置套接字选项
2017-12-29 08:21 441下面几种方法可用 ... -
I/O 复用之 poll 函数
2017-12-27 00:20 423poll 函数提供的功能与 select 类似,不过在 ... -
I/O 复用之select 函数
2017-12-12 00:32 516select 函数允许进 ... -
套接字创建、连接和关闭函数
2017-08-13 17:16 664下图是一对 TCP 客户与服务器进程之间发生的一些典型 ... -
字节转换和填充函数
2017-08-06 01:09 428网络编程中,为保证发送协议栈和接收协议栈就如 32 位 ... -
IPv4 和 IPv6 的套接字地址结构
2017-08-01 21:03 738大多数套接字函数 ...
相关推荐
Linux IO 通信模型概述 在 Linux 系统中,IO 通信模型是网络编程的基础。理解不同的 IO 模型对于服务器领域的开发者非常重要。本文将从 Unix/Linux 接口出发,介绍几种常用的 IO 模型,并分析它们的优缺点。 阻塞...
事件通知是重叠IO模型中的关键部分,它通常依赖于信号量、事件对象或文件描述符(在Unix系统中)来告知线程何时有I/O操作完成。在C++中,我们可以使用Windows API中的CreateIoCompletionPort函数创建IOCP,然后使用...
Unix域协议是Unix和类Unix系统中一个高效的本地进程通信机制,它提供与网络协议一致的API,简化了编程模型。虽然其他IPC机制如消息队列、共享内存、命名管道等也有各自的优势,但Unix域协议的接口兼容性使其在很多...
### Java IO学习基础之读写文本文件 #### 一、Java IO概述 Java IO(Input/Output)是Java中处理输入输出操作的...在实际应用中,还需要根据具体需求选择合适的IO模型,并注意异常处理,确保程序的健壮性和稳定性。
**网络模型概述** 在计算机网络编程中,有多种模型用于处理多路复用,以便一个进程可以同时处理多个网络连接。其中,`select`模型是一种经典的解决方案,尤其适用于早期的Unix系统。本篇将深入探讨`select`模型的...
4. **信号处理**:Unix中的信号机制是一种异步事件通知机制,如SIGINT(中断)、SIGTERM(终止)等。学习如何捕获、处理和忽略信号对于编写健壮的程序至关重要。 5. **网络编程**:Unix系统提供了丰富的网络编程...
### Unix环境高级编程知识点概述 #### 一、Unix环境编程概览 - **Unix系统简介**:Unix是一种多用户、多任务的操作系统,其稳定性和安全性极高,广泛应用于服务器领域。Unix提供了丰富的命令行工具和API接口,支持...
### Unix编程环境概述 #### 1. **Unix系统简介** - **起源与历史**:Unix操作系统最早由Ken Thompson在1969年开发,随后由他和他的同事Dennis Ritchie等人不断完善和发展。 - **特点**:Unix是一种多用户、多任务...
- 使用非阻塞IO模型。 - 合理分配内存资源。 - **安全措施**: - 文件权限管理:设置适当的权限避免非法访问。 - 数据加密传输:SSL/TLS协议保护敏感信息。 - 输入验证:防止SQL注入、XSS攻击等漏洞。 #### 四...
Unix/Linux上的五种IO模型 - **阻塞IO(Blocking I/O)**:传统的IO模型,当进程调用读或写操作时,若数据未准备好,进程就会阻塞,直到数据准备好为止。 - **非阻塞IO(Non-blocking I/O)**:与阻塞IO不同,当...
- **改进的气象接口**:增强了与气象模型(如 MM5)的交互能力。 - **优化的性能**:通过代码优化,显著提升了模型运行效率。 **1.6 关于手册** 本手册旨在为用户提供全面的指导,涵盖了从安装配置到实际应用的各个...
全面理解 Java 网络编程 - BIO、NIO、AIO 本课程旨在帮助学生全面理解 Java ...Unix 中的 Socket 是一种特殊的文件描述符,提供了进程间通信的基础。 通过 Socket,客户端可以与服务器之间建立连接,实现数据的传输。
- **Unix的五种IO模型**: - **阻塞IO(Blocked IO)**:程序在读写操作期间被挂起。 - **非阻塞IO(Non-blocking IO)**:程序可以查询I/O状态并进行读写。 - **IO多路复用(IO Multiplexing)**:使用select或epoll等...
9.3.4 信号驱动IO模型 258 9.3.5 异步IO模型 258 9.4 select()函数和pselect()函数 259 9.4.1 select()函数 259 9.4.2 pselect()函数 261 9.5 poll()函数和ppoll()函数 262 9.5.1 poll()函数 263 ...
通用文件模型是Linux文件系统的核心组成部分,主要包括四种对象类型:超级块对象、索引节点对象、文件对象和目录项对象。这些对象共同构成了文件系统的数据结构基础。 - **超级块对象**:存储文件系统的元数据,如...
异步IO模型允许在等待IO操作完成的同时执行其他任务,从而提高了系统的整体性能。 4. **非阻塞编程**:与异步IO类似,非阻塞编程也是提高并发能力的有效手段。在非阻塞模式下,当没有数据可读或写时,不会阻塞当前...
网络编程概念是学习网络编程的基础,包括阻塞和非阻塞编程模式、Select 模型、WSAAsyncSelect 模型、IO 重叠模型、完成端口模型等。了解这些概念可以帮助开发者更好地开发网络应用程序。 学习资源 学习 Windows ...
**Windows Socket**(简称 Winsock)是一种在微软Windows系统中实现网络编程接口的标准,源自于UNIX Socket,主要用于TCP/IP网络通信。它允许应用程序通过TCP/IP协议进行数据交换,是Windows平台上进行网络编程的...
10.IO multiplexing(IO多路复用):IO多路复用是一种用来提高网络吞吐量的技术,允许单个线程或进程同时处理多个网络连接。select()和poll()都是常用的IO多路复用机制。 11.close():close()函数用于关闭套接字,...