Java教程

09阻塞与非阻塞I/O,同步与异步I/O,I/O复用

本文主要是介绍09阻塞与非阻塞I/O,同步与异步I/O,I/O复用,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

一、阻塞与非阻塞I/O

image
image

阻塞与非阻塞I/O
阻塞和非阻塞主要是指调用某个系统函数时,这个函数是否会导致我们的进程进入 sleep()【卡在这休眠】状态而言的;
a)阻塞I/O
我调用一个函数,这个函数就卡在在这里,整个程序流程不往下走了【休眠sleep】,该函数卡在这里等待一个事情发生,
只有这个事情发生了,这个函数才会往下走;这种函数,就认为是阻塞函数;accept();
//阻塞还是非阻塞的判断是根据监听套接字的种类
这种阻塞,并不好,效率很低;一般我们不会用阻塞方式来写服务器程序,效率低;
b)非阻塞I/O:不会卡住,充分利用时间片,执行更高;
非阻塞模式的两个鲜明特点:
    (1)不断的调用accept(),recvfrom()函数来检查有没有数据到来,如果没有,函数会返回一个特殊的错误标记来告诉你,这种标记可能是EWULDBLOCK,也可能是EAGAIN;
(不叫错误,叫标记)如果数据没到来,那么这里有机会执行其他函数,但是也得不停的再次调用accept(),recvfrom()来检查数据是否到来,非常累;
//for(),不停的轮accept(),recvfrom(),依旧还是在一个进程中
    (2)如果数据到来,那么操作就得卡在这里把数据从内核缓冲区复制到用户缓冲区,所以复制这个阶段是"卡着"完成的;

二、同步与异步I/O

image
image

a)异步I/O:
事先准备工作:调用一个异步I/O函数时,我门要给这个函数指定一个“接收缓冲区”,我还要给定一个“回调函数”;

调用完一个异步I/O函数后,该函数会立即返回。 其余判断交给操作系统,操作系统会判断数据是否到来,
如果数据到来了,操作系统会把数据拷贝到你所提供的缓冲区里,然后调用你所指定的这个回调函数来通知你;
//==>通知

很容易区别非阻塞和异步I/O的差别:
    (1)非阻塞I/O要不停的调用I/O函数来检查数据是否来,
	如果数据来了,就得卡在I/O函数这里把数据从内核缓冲区复制到用户缓冲区,然后这个函数才能返回;
    (2)异步I/O根本不需要不停的调用I/O函数来检查数据是否到来,只需要调用一次,然后就可以干别的事情去了;
	内核判断数据到来,拷贝数据到你提供的缓冲区,调用你的回调函数来通知你,你并没有被卡在那里的情况;
	
b)同步I/O
    select/poll(能力不太行)。     epoll(最强)。
    1)调用select()判断有没有数据,有数据,走下来,没数据卡在那里;
    2)select()返回之后,用 recvfrom() 去取数据;当然取数据的时候也会卡那么一下;
同步I/O感觉更麻烦,要调用两个函数才能把数据拿到手;
-----------------------------------------存在即合理
但是同步I/O和阻塞式I/O比:就是所谓的 I/O复用【用两个函数来收数据的优势】 能力;***

三、I/O复用----同步IO的能力是I/O复用

所谓I/O复用,就是我多个socket【多个TCP连接】可以弄成一捆【一堆】,
我可以用select这种同步I/O函数在这等数据;
select()的能力是等多条TCP连接上的任意一条有数据来(检测一堆);
然后哪条TCP有数据来,我再用具体的比如recvfrom()去收。
所以,这种调用一个函数能够判断一堆TCP连接是否来数据的这种能力,
叫I/O复用,英文I/O multiplexing【I/O多路复用】==多用

分类

行业分类:
   很多资料把 阻塞I/O,非阻塞I/O,同步I/O归结为一类 ,因为他们多多少少的都有阻塞的行为发生;
   甚至有的资料直接就把 阻塞I/O,非阻塞I/O 都归结为同步I/O模型,这也是可以的】
   而把异步I/O单独归结为一类,因为异步I/O是真正的没有阻塞行为发生的;

image

这篇关于09阻塞与非阻塞I/O,同步与异步I/O,I/O复用的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!