当前位置: 首页 > 科技观察

其实Linux的IO模型并没有那么难

时间:2023-03-14 00:09:19 科技观察

IO其实就是Input和Output,对应操作系统中数据流的输入输出。这个数据流的两端可以是文件,也可以是网络上的主机。但无论是文件还是网络主机,传输都是类似的。今天我们就以源为文件来进行讲解。一个文件从磁盘到我们的内存需要经过非常复杂的操作。首先需要从硬件中读取数据,然后放入操作系统内核缓冲区,然后将数据复制到程序缓冲区,最后应用程序才能读取文件。简单的说,不管是什么IO模型,读取过程总会经历以下两个阶段:等待数据到达内核缓冲区将数据从内核缓冲区复制到程序缓冲区我们Linux分为五种经典的IO模型介绍一下,即:阻塞IO模型非阻塞IO模型IO多路复用模型信号驱动IO模型异步IO模型阻塞IO模型阻塞IO称为BlockingIO,简称BIO。在阻塞IO模型中,当一个进程发起读文件请求(recvfrom系统调用)时,如果内核缓存中没有对应的数据,则不会立即恢复,而是会读取磁盘数据,当数据被读取时然后,返回流程。至此,第一阶段完成。在此阶段,进程被阻塞,因为它正在等待内核将数据读入内核缓冲区。进程收到内核的响应后,将数据从内核缓冲区复制到程序缓冲区,最终完成文件读取操作。至此,第二阶段完成。该进程也在这个阶段被阻塞,因为它必须将数据从内核缓冲区复制到程序缓冲区。简单的说:在阻塞IO模型中,从硬件到系统内核,从系统内核到程序空间,都是阻塞的。非阻塞IO模型在非阻塞IO模型下,当一个请求发起读取文件请求(recvfrom)时,如果内核缓冲区中没有数据,内核会读取文件数据。但是此时请求并不会被阻塞,而是会返回一个错误信息(EWOULDBLOCK)告诉进程:数据还没有准备好,请稍后再试。于是进程不停地向内核重试,询问:数据准备好了吗,数据准备好了吗……当内核准备好数据时,进程就会收到相应的消息,这样第一阶段就结束了。Non-blockingIO中的Non-blocking是指进程不会阻塞在这里,而是会不断重试。虽然这样用处不大,会让CPU闲置,但比以前好一点点。该过程在此阶段未被阻止。当进程知道内核准备好数据时,它会将数据从内核缓冲区复制到程序缓冲区。这个阶段和阻塞I/O模型完全一样,同样会导致进程阻塞。简单的说:在非阻塞IO模型中,从硬件到系统内核,从系统内核到程序空间,都是阻塞的。但它比阻塞IO更具竞争力。它不会静止不动,但无论如何都会运行一段时间。虽然是在做无用功,但是却提高了一点点效率。IO多路复用模型IO多路复用之所以称为多路复用,是因为它可以同时操作多个数据流。以前的阻塞IO和非阻塞IO一次只能操作一个数据流。在IO多路复用模型中,一个进程监听多个数据流并阻塞它们。当任何一个数据流有数据时,它都会收到内核的响应。至此,第一阶段完成,进程实际上在这个阶段被阻塞。进程收到内核的响应后,会将数据从内核缓冲区复制到程序缓冲区。这个阶段和上面两个模型完全一样,过程也是阻塞的。简单的说:IO多路复用模型与第二阶段的阻塞IO和非阻塞IO是完全一致的。但是在第一阶段,它的效率有了很大的提升,可以同时轮询多个数据流,提高了效率。Signal-drivenIOmodelsignal-driven和之前模型的区别就是信号这个词。在信号驱动IO的第一阶段,即数据到达内核缓冲区之前,进程不阻塞,而是设置一个信号回调。当数据到达内核缓冲区时,内核调用程序的回调。这样,信号驱动IO下的进程就可以不阻塞了,可以做其他事情。当进程接收到信号时,进程将数据从内核缓冲区复制到程序缓冲区。这个过程和上面的完全一样,也是阻塞的。信号驱动IO可以说是IO读取的一个里程碑,真正实现了数据的异步读取。信号驱动第二阶段IO,同上。但它在第一阶段是真正异步的。在信号驱动IO的第一阶段,它请求内核读取数据。此时不会阻塞或搜索轮子,而是设置一个信号回调。当数据完全复制到系统内核后,系统发送SIGIO信号通知进程进入第二阶段,将数据复制到程序缓冲区。异步IO模型与前面的流程相比,异步IO是完全非阻塞的。第一阶段和第二阶段都是非阻塞的。与信号驱动IO类似,异步IO模型通过信号回调实现第一阶段进程的非阻塞。当数据到达内核缓冲区时,进程将得到通知。进程收到通知后,再次将内核缓冲区中的数据复制到进程缓冲区中,但此时进程并没有等待,还设置了一个信号回调。当复制完成后,进程收到通知,然后进行相应的处理。与信号驱动IO相比,异步IO更彻底!异步IO不仅在第一阶段实现了信号回调,在第二阶段也实现了信号回调,从而完全实现了异步IO操作。综上所述,让我们回顾一下这5种IO模型,分两个阶段根据它们的特点来区分:阻塞IO模型:硬件到系统内核,阻塞。系统内核到程序空间,阻塞。非阻塞IO模型:硬件到系统内核,轮询阻塞。系统内核到程序空间,阻塞。多路复用IO模型:硬件到系统内核,多流轮询和阻塞。系统内核到程序空间,阻塞。信号驱动IO模型:硬件到系统内核,信号回调不阻塞。系统内核到程序空间,阻塞。异步IO模型:硬件到系统内核,信号回调不阻塞。从系统内核到程序空间,信号回调是不阻塞的。从上面的五种IO模型我们可以看出,只有异步IO模型才是真正的异步非阻塞,其他四种都是同步IO。因为在第二阶段:从内核缓冲区复制到进程缓冲区的时候,不可能再做其他事情了。本文转载自微信公众号“陈淑仪”,可通过以下二维码关注。转载本文请联系陈淑仪公众号。