IO 模型

1、简述

(注:以下文字毫无权威性,建议想了解的买本权威操作系统书籍翻到 IO 部分推荐《UNIX环境高级编程》+《UNIX网络编程》进行阅读)

IO 设备分为很多种,如存储设备(如磁盘)、传输设备(如网卡)、人机交互设备(鼠标键盘等),计算机的操作系统在与 IO 设备的设备控制器进行数据交互时衍生出了许许多多交互的方法/协议。主机与控制器交互的完成协议可能会十分复杂,但是基本握手的概念则相对不复杂,握手即你可以将主机和设备控制器看成一个生产者和消费者模型,那么设备控制器是如何和主机进行相互通知和交互来进行读写处理,其中就有轮询、中断、DMA、通道等方式。说完主机与设备控制器之间的握手,接下来再说一个问题,事实上大量不同的外设为操作系统的设计实现提出了一个问题——每种设备都有自己的功能,交互的协议都不尽相同,如何设计操作系统以使得心的外设可以直接加到计算机上而不必重写操作系统,是不是有点蜜汁熟悉?计算机技术的发展始终和标准统一分不开,设立标准的含义之远大也是大家在学习计算机相关知识有所体会的,扯远了,刚刚其实就是说操作系统如何提供一个统一、方便的应用程序IO端口,总而言之,操作系统需要给上层应用封装并提供一些接口或者系统调用来让应用程序得以方便的通过操作系统与 IO 设备交互,例如在磁盘 IO 中大部分主流操作系统都会提供诸如 read、write、seek 等函数,又例如在网络设备 IO 中,由于网络 IO 的性能和访问特点与磁盘 IO 相比有很大差别,绝大多数的操作系统所提供的网络 IO 接口是网络 Socket 接口,如 Linux 系统中内核底层提供了 poll、select、epoll 等系统调用。废话说了那么多,现在说重点,你可能听过 JAVA IO包及NIO包、redis同步非阻塞通信机制原理、nginx服务端和客户端通信采用同步非阻塞等等,其实都是和操作系统底层的网络 IO 接口原理分不开,你例如 nginx 在 linux 上就用到了 epoll,所以在学习这些操作系统之上的应用程序(JAVA/JVM、redis、nginx……)的IO或者说网络通信模型之前,非常有必要了解操作系统提供的一些系统调用及如何体现同步阻塞、同步非阻塞等诸如此类的概念,了解好了这些,再去学习应用程序通信机制的时候就不会很多文章看的一头雾水。

 

2、推荐阅读

Linux IO模式及 select、poll、epoll详解

马士兵 bilibili 视频:深入 IO 到 EPOLL

知乎:怎样理解阻塞非阻塞与同步异步的区别?

最后,打开 linux 用 man 看看 epoll、poll、select 再配合百度:poll、epoll、select 底层实现原理

 

3、关于非阻塞和异步的区别

这一点你打开上面知乎的链接便可以看到讨论的很多,其中最让人迷惑的便是同步非阻塞和异步非阻塞,特别是 epoll,这个系统调用我一开始也认为是个异步,但是根据 POSIX 的定义,它实际上是个同步非阻塞的实现。强烈建议看看上面链接的第一个链接,基本上给出了正解,这里再补充一个《操作系统概念》里面提供的解释。可以看到,实际上只要请求方你还是自己有读这个操作,那么你就是同步的,读取数据例如调用 recvfrom 这件事情只要是你自己干的,那么便不能称为异步。

 

再啰嗦一下,同步和异步的定义,下面摘自《UNIX网络编程》

 

翻译一下就是,同步的 IO 操作就是请求 IO 过程中有被阻塞,而异步则不会被阻塞。使用这个定义的话,那么阻塞、非阻塞、多路复用、信号驱动的 IO 全都是同步的 IO,只有真正的异步 IO 模型才符合上面关于异步 IO 的定义。

 

在我提供的推荐阅读链接第一条里面也提到,实际上 IO 你可以分为两个阶段,一个是等待阶段(等待响应方发来数据)还有一个是读取阶段,即将内核空间的数据读取到应用程序的用户空间当中去,在同步非阻塞模型下(如epoll),recvfrom 阶段还是被阻塞了,所以它的同步的。而真正异步的情况如下高赞回答

 

posted @ 2020-05-05 22:21  qwerity  阅读(141)  评论(0编辑  收藏  举报