OS中的阻塞与非阻塞IO、同步与异步IO

本文最后更新于:3 个月前

前言

IO 指的是用户态的进程,需要操作系统帮助其进行数据的读入和写出。

以 IN 为例,可以分为两个步骤:从磁盘、网络等地方将数据放到内核空间(准备内核数据)、数据从内核空间拷贝到用户空间(内核空间的数据拷贝到用户空间)。


阻塞 I/O

阻塞 I/O 阻塞等待的是两个过程:准备内核数据 和 内核数据拷贝到用户空间。

用户进程需要数据的时候,调用 read() 函数,然后用户进程阻塞,直到数据拷贝到用户空间。

image-20221121152445935

非阻塞 I/O

非阻塞 I/O 阻塞只等待一个过程准备内核数据 和 内核数据拷贝到用户空间。

当发起非阻塞的 IO 之后,如果发现需要的数据在内核中未准备好,那么直接返回,不等待。然后通过不断轮询内核,来查看有没有准备好数据。如果准备好了数据,那么用户进程再阻塞,等待数据从内核空间拷贝到用户空间这一过程。

image-20221121153225613

基于非阻塞的 I/O 多路复用

非阻塞 I/O 存在问题:当数据未准备好的时候,用户进程需要不断地去轮询内核,查看数据准备好了没有。这个不断轮询的过程,导致用户进程没办法做其它的事情。因此引入了 I/O 多路复用技术。

I/O 多路复用技术:内核数据为装备好的时候,用户直接返回,不阻塞,且不轮询。当内核中的数据准备好之后,以事件通知应⽤程序过来拿数据。

image-20221121161111685

同步 I/O

⽆论是阻塞 I/O、还是⾮阻塞 I/O、非阻塞I/O多路复用,都是同步调⽤。

因为它们在read调⽤时,第二个过程-内核将数据从内核空间拷⻉到应⽤程序空间,这个过程都是需要等待的,也就是说这个过程是同步的。

如果内核实现的拷⻉效率不⾼,read调⽤就会在这个同步过程中等待⽐较⻓的时间。


异步 I/O

真正的异步 I/O 是内核数据准备好数据从内核态拷⻉到⽤户态这两个过程都不⽤等待。

发起 aio_read 之后,就⽴即返回,内核⾃动将数据从内核空间拷⻉到应⽤程序空间,这个拷⻉过程同样是异步的,内核⾃动完成的,和前⾯的同步操作不⼀样,应⽤程序并不需要主动发起拷⻉动作。

image-20221121162857355

OS中的阻塞与非阻塞IO、同步与异步IO
https://alec-97.github.io/posts/2169254623/
作者
Shuai Zhao
发布于
2022年11月21日
许可协议