UNIX 5种I/O模型

Unix 5 I/O模型

I/O操作分为两步:

(1)先将数据从 存储介质 (磁盘或者网络等)拷贝到 内核缓冲区,此时称为数据准备好,可以被用户读取。

(2)由用户应用程序拷贝内核缓冲区数据 到用户缓冲区。

1.阻塞I/O模型

函数 recfrom 视为系统调用。 不论该函数如何实现, 都会有 从应用进程中运行 到 内核中运行的 切换, 一段时间以后 还会有 一个返回 到应用进程的切换。

应用程序 调用一个I/O 函数, 导致应用程序阻塞 并等待数据准备就绪。 如果数据没有准备好 就一直等待。 如果数据准备好了, 则从内核拷贝到用户空间拷贝数据,IO函数 返回成功指示。

进程调用 recvfrom 此系统调用 直到 数据报到达 且被复制到应用进程的缓冲区中 或发生 错误才返回, 常见的错误如 系统调用被信号中断。

进程在调用 recvfrom开始 到它 返回的 整段时间内是阻塞的, 该函数成功返回后,应用程序 开始处理 数据报。

2.非阻塞I/O模型 (数据就绪之前 一直轮询)

非阻塞接口 告诉内核 ,当所请求的IO未完成时,返回一个错误,而不是将进程睡眠。 因此,IO操作函数将不断的测试,数据是否已经准备好了。
不断轮询,直到数据准备好为止。

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

当一个应用进程 非阻塞 循环调用 recvfrom时,我们称为轮询 polling 。

3.I/O 复用模型 (select poll)

I/O 复用模型会用到 select 或者 poll 函数, 这两个函数也会使进程阻塞, 但是和阻塞I/O不同的是,这两个函数 可以 同时阻塞多个I/O操作。
而且可以同时 对多个读操作,多个写操作的 I/O 函数 进行检测, 直到有数据可读 可写才真正调用 IO操作函数。

只要有数据就绪, select 调用返回, 应用程序调用 recvfrom 将数据 从内核区拷贝至 用户区。

优势在于,每次select阻塞 结束返回后, 可以获得多个准备就绪的套接字(即一个select 可以对多个套接字进行管理,类似于同时监控多个套接字事件是否就绪)。

和阻塞IO相比较, select I/O 复用模型相当于提前阻塞了。 等到有数据到来时,再调用revcfrom函数 就不会因为要等数据而发生阻塞。

4.信号驱动 I/O模型

让内核在数据就绪时 用信号SIGIO通知应用程序。
首先,允许套接字进行信号驱动I/O, 并通过系统调用sigaction 安装一个信号处理程序。 此系统调用立即返回,进程继续工作,它非阻塞。
当数据报 准备好被读时,就为该进程生成一个 SIGIO 信号。 应用程序可以在信号处理程序用 调用 revcfrom 来读取数据报。

5.异步I/O

让内核启动操作, 在整个操作完成后(将数据 从内核拷贝到 用户空间) 通知应用程序。

调用aio_read函数, 告诉内核描述字, 缓冲区指针,缓冲区大小, 文件偏移以及通知的方式,然后立即返回。 当内核将数据拷贝到缓冲区后,在通知 应用程序。

五种IO 模型对比:

文中涉及的 unix 函数:

The recvfrom() and recvmsg() 调用用于从套接字接收消息,并且可以被用于接收套接字上的数据是否是面向连接的。

原文地址:https://www.cnblogs.com/ironbrady/p/8572982.html