同步IO、异步IO、阻塞IO、非阻塞IO

一直对这四个东东的概念很模糊,放一起更模糊,根据别人写的总结一如下:
“阻塞”与”非阻塞”与”同步”与“异步”不能简单的从字面理解,往往不同上下文中它们的意思是不一样的。

1.同步 / 异步(同步/异步主要针对C端: )描述的是执行IO操作的主体是谁,同步是由用户进程自己去执行最终的IO操作。异步是用户进程自己不关系实际IO操作的过程,只需要由内核在IO完成后通知它既可,由内核进程来执行最终的IO操作

2.阻塞与非阻塞(阻塞/非阻塞主要针对S端:)
阻塞 / 非阻塞描述的是函数,指访问某个函数时是否会阻塞线程(block,线程进入阻塞状态)。

同步和异步,阻塞和非阻塞,有些混用,其实它们完全不是一回事,而且它们修饰的对象也不相同。
阻塞和非阻塞是指当server端的进程访问的数据如果尚未就绪,进程是否需要等待,简单说这相当于函数内部的实现区别,也就是未就绪时是直接返回还是等待就绪;
而同步和异步是指client端访问数据的机制,同步一般指主动请求并等待I/O操作完毕的方式,当数据就绪后在读写的时候必须阻塞(区别就绪与读写二个阶段,同步的读写必须阻塞),异步则指主动请求数据后便可以继续处理其它任务,随后等待I/O,操作完毕的通知,这可以使进程在数据读写时也不阻塞。(等待”通知”)

3.非阻塞同步IO指的是用户调用读写方法是不阻塞的,立刻返回的,而且需要用户线程来检查IO状态。需要注意的是,如果发现有可以操作的IO,那么实际用户进程还是会阻塞等待内核复制数据到用户进程,它与同步阻塞IO的区别是后者全程等待。

非阻塞异步IO指的是用户调用读写方法是不阻塞的,立刻返回,而且用户不需要关注读写,只需要提供回调操作,内核线程在完成读写后回调用户提供的callback

4.这两个概念的不同造成了编程模型的不同。

非阻塞同步IO由于读写方法非阻塞,并且需要用户自己来进行读写,所以每次调用读写方法实际读写的字节数是不确定的,所以需要一个Buffer来保存每次读写的字节状态。更重要的是用户不知道什么时候完成了读写,一般需要用while循环判断Buffer的状态来跟踪读写。

非阻塞异步IO由于是内核线程进行读写,并且在IO完成后会回调用户提供的callback,编程模型就比较简单,用户只需要调用读写,提供回调就可以了,比如 read(filename, callback)

5.Linux下的五种I/O模型
1)阻塞I/O(blocking I/O)
2)非阻塞I/O (nonblocking I/O)
3) I/O复用(select 和poll) (I/O multiplexing)
4)信号驱动I/O (signal driven I/O (SIGIO))
5)异步I/O (asynchronous I/O (the POSIX aio_functions))

前四种都是同步,只有最后一种才是异步IO。

最后个人认为:

阻塞:某个任务请求资源Ai,如果不可以立即获得资源,进程就会卡在这里。比如服务端阻塞listen,没有客户端连接进来,进程就卡在这里;或者是一直在读缓冲区,缓冲区没有数据,读进程就卡在这里;
非阻塞:某个任务请求资源Ai,如果不可立即获得资源,就放弃本次请求,并返回。比如服务端非阻塞listen,如果没有客户端连接进来,就返回;或者是在读缓冲区,管缓冲区没有数据就返回。
同步:进程没办法知道数据什么时候才真正读取完毕了,所以需要每隔一段时间就去轮询一下,重新调用 read,看是不是数据真的已经读取完毕了;
异步:调用在发出之后,这个调用就直接返回了,立刻就可以开始去做其它的事,所以没有返回结果;等read读取完毕就会通知进程过来处理数据。另一方面,从kernel的角度,当它收到一个异步read之后,首先它会立刻返回,所以不会对用户进程产生任何阻塞。然后,kernel会等待数据准备完成,然后将数据拷贝到用户内存,当这一切都完成之后,kernel会给用户进程发送一个signal,告诉它read操作完成了。

猜你喜欢

转载自blog.csdn.net/qiangzhenyi1207/article/details/79080132