在UNP1中Stevens老爷子先把主要是把IO分为了两个阶段:
①等待socket描述符就绪
②将数据从内核复制到用户空间
然后给出了5种IO模型:阻塞式IO、非阻塞式IO,IO复用、信号驱动式IO、异步IO。具体见UNP1的6.2节。
但是他并没有给出阻塞IO与非阻塞IO,同步IO与异步IO的明确定义。
今天看到一篇译文,感觉对IO进行了比较好的明确的说明。
文章出处:http://blog.jobbole.com/59676/
它的分类主要是参考了两本书,一本当然也是UNP1,另一本是C++ Network Programming,作者Douglas C. Schmidt
①阻塞型
正常的read,调用read将会使线程阻塞知道读到数据。
②非阻塞同步型
使用fcntl函数将套接字设置为异步的,调用read的时候,如果套接字没有准备好,同样立即返回。
③非阻塞异步型
比如Windows里面的ReadFile()或者POSIX里面的aio_read()。
调用立即返回,并且相当于提交了任务,系统会使用另外的资源或者线程来完成该任务。并在任务完成时,通知调用者(比如通过回调函数)
所以总结起来,
阻塞与非阻塞
阻塞就是说调用函数后控制权就交给该函数了,而不是立即返回一个结果。
严格说起来,上面给出的②非阻塞同步型的read仍然可能是一个阻塞函数。
在socket没有内容需要读的时候,它立即返回,这时它是非阻塞的。
在socket有内容需要读的时候,它会阻塞去读取,但是由于这个时候的读取是从内核到用户区,且大小一般不是特别大,
所以可以看做等待socket就绪这件事情的高阶无穷小,从这个层面来说也就可以看做非阻塞的了。
同步和异步
可以看做是能不能将一部分工作交给系统去做,而非用户代码。
比如aio_read就是将等待socket就绪,以及将数据从内核复制到用户空间都交给操作系统(不管操作系统实现上是开多线程还是什么,所以异步这种操作需要操作系统本身支持)去做,
然后做好了通知自己。
这就是我理解的阻塞,非阻塞。同步,异步。