常见的Linux IO模型:
阻塞IO模型:当应用程序调用read或write等IO操作时,如果内核没有准备好数据,那么应用程序就会一直阻塞等待,直到内核准备好数据后才会返回。在这种模型下,应用程序通常只能同时处理一个连接,效率较低。
非阻塞IO模型:当应用程序调用read或write等IO操作后,如果内核没有准备好数据,那么应用程序不会被阻塞,而是立即返回一个Eagain或EWouldBlock错误码,表示当前资源不可用。在这种模型下,应用程序需要不断轮询来检查是否有数据准备好,可以同时处理多个连接,但轮序频繁可能会占用过多CPU资源。
IO复用模型:使用select、poll或epoll等系统调用来监听多个IO事件,当有IO事件发生时再进行处理。在这种模型下,应用程序也只需要通过一个线程来监听多个连接,效率比非阻塞IO模型要高。
信号驱动IO模型:应用程序调用sigaction函数注册一个信号处理函数,在数据准备好时内核会向应用程序发送一个SIGIO信号,应用程序收到信号后再进行IO操作。这种模型比较适合于处理低频率的IO事件。
异步IO模型:应用程序调用aio_read或aio_write等异步IO函数,内核会在IO操作完成后通知应用程序。在这种模型下,应用程序不需要等待IO操作完成,可以继续执行其他任务,当IO操作完成后再进行回调处理。异步IO模型在高并发场景下更具优势。
注意:在非阻塞IO模型中,应用程序每一次轮询检查数据是否准备好时,都会涉及到从用户态到内核态的切换。因此对于非阻塞IO模型,每一次轮询都是昂贵的系统调用。
而非阻塞IO模型与多路复用IO模型的区别就在于:
多路复用IO模型将轮询的任务交给了操作系统,由操作系统对连接进行监听,当有事件时才会返回向用户态的应用程序返回事件列表。大大减少了用户态和内核态切换的系统调用开销。
参考:
计算机网络——阻塞IO、非阻塞IO、IO多路复用
美团后端开发暑期实习一面