Linux的IO模型中,应用从网络读取数据时,会经历两个步骤:
- 等待网络数据到达,然后DMA拷贝到内核缓冲区;
- 数据从内核缓冲区拷贝到应用缓冲区;
针对这两个阶段,Linux提供了5种网络IO模型:
- 阻塞IO模型;
- 非阻塞IO模型;
- IO复用模型;
- 信号驱动IO模型;
- 异步IO模型;
阻塞IO模型
应用进行系统调用,阻塞等待直至数据到达被拷贝到用户缓冲区,或者发生错误,如下图所示:
缺点:一个线程处理一个FD,且会阻塞;
非阻塞IO模型
应用进行系统调用,如果内核缓冲区没有数据则直接返回,应用需要通过轮询检查内核缓冲区是否有数据到来,如下图所示:
缺点:一个线程处理一个FD,不断轮询获取数据状态;
IO多路复用模型
一个线程同时处理多个FD,即复用线程。以select/poll函数为例说明,应用进行系统调用时将FD集合传递给select/poll函数,然后阻塞直至其中某些FD变为可读或可写,如下图所示:
优点:线程复用,一个线程可以处理多个FD;
信号驱动IO模型
当内核缓冲区数据准备好之后,系统会产生信号通知应用程序,再由应用发起系统调用将数据从内核缓冲区拷贝到用户空间,如下图所示:
异步IO模型
应用发起系统调用向内核注册回调函数,当数据准备好并且拷贝到用户空间之后,内核回调应用注册的函数进行处理,如下图所示:
优点:完全异步化,无阻塞;