转载:IO模型

简介
参考《UNIX Network Programming Volume 1, ThirdEdition [Electronic resources] : The Sockets Networking API》
进程运行状态分为内核态和用户态两种。
对于文件读取:
第一步:等待数据准备
第二步:将数据从内核空间复制到用户空间中
对于socket:
第一步:等待网络上的数据到达,然后被复制到内核空间
第二步:将数据从内核空间复制到用户空间中
 
同步与异步
同步与异步关注的是进程与内核的交互。同步进程触发IO并等待或者轮询IO是否完成。 异步进程触发IO后直接返回,IO交给内核来处理,完成后内核通知进程IO完成。
 
阻塞与非阻塞
阻塞和非阻塞关注的是进程(线程)在等待调用结果时的状态。阻塞是指调用结果返回之前,当前进程(线程)会被挂起。非阻塞则相反,当前进程(线程)不会被挂起。
 
同步阻塞IO模型
 
进程执行recvfrom系统调用后进程阻塞,等待数据准备好,此时进程让出CPU。当数据准备好后,等待内核将数据复制到用户空间。复制完成后,recvfrom系统调用返回成功,进程解除阻塞。此模型特点是IO过程的两步都会等待。
 
同步非阻塞IO模型
 
进程执行recvfrom系统调用,如果数据还没有准备好,那么recvfrom系统调用返回一个错误。这个过程一直重复,直到数据准备好后,等待内核将数据复制到用户空间。复制完成后,recvfrom系统调用返回成功。此模型特点是,IO过程的第一步不需要等待,而是进程需要不断地询问内核数据是否准备好,此时进程不会让出CPU,而会一直占用CPU,浪费了大量的CPU资源,因此不常用。
 
多路复用IO模型
 
进程执行select系统调用后,进程阻塞。内核监控多个套接字,当某个套接字数据准备好了,则select系统调用返回。此时进程发起recvfrom系统调用,内核将数据复制到用户空间。复制完成后,recvfrom系统调用返回成功。此模型特点是,对于单个IO操作,和阻塞IO相比并没有什么不同。事实上,还更差一些。因为这里需要使用两个系统调用(select 和 recvfrom),而阻塞IO只调用了一个system call (recvfrom)。不过它适合于同时处理多个IO操作,当其中的任意一个进入可读状态,select系统调用就可以返回。在非阻塞IO中,不断地询问socket状态是通过用户进程去进行的,而在多路复用IO中,轮询每个socket状态是内核在进行的,这个效率要比用户进程高的多。
 
信号驱动IO模型
在信号驱动IO模型中,给某个的IO操作注册一个信号处理函数,进程发起sigaction系统调用,等待数据准备好,此时并不会阻塞,用户进程可以执行别的任务。当内核数据准备好了,就会发送一个信号给用户进程,用户进程接收到信号之后,便在信号处理函数中执行recvfrom系统调用,内核将数据复制到用户空间。复制完成后,recvfrom系统调用返回成功。这个模型并不是真正的异步,因为用户进程还要执行recvfrom系统调用,这一步需要等待。
 
异步IO模型
进程执行aio_read系统调用,该系统调用立即返回。具体的数据准备和复制全部由内核来完成,用户进程可以执行别的任务。
 
总结
同步有阻塞和非阻塞之分,异步没有,它一定是非阻塞的,所以不存在异步阻塞和异步非阻塞的说法。
多路复用和信号驱动,在处理业务逻辑上可以说有异步,但在IO操作层面上来说还是同步的。posix.1严格定义的异步IO是要求没有任何一点阻塞,而上述的前面四个(阻塞IO,非阻塞IO,IO复用,信号驱动)都不同程度阻塞了,而且都有一个共同的阻塞: 将数据从内核空间复制到进程空间。
原文地址:https://www.cnblogs.com/gjb724332682/p/11524039.html