这里之前不是很理解非阻塞和异步的差别,感觉很相似但感觉又是有差别的,但是就表达不了。
现在来弄懂。
首先,需要知道有两个过程:
1.「内核数据准备好」
2.「数据从内核态拷贝到用户态」
用read()函数举例子。
应用程序向系统发出read()请求,而这时内核缓冲区还没有数据,即内核数据还未就绪,
1)若是阻塞i/o的话,就会一直阻塞等到内核数据准备好,就调用read()函数;
2)若是非阻塞i/o的话,就不会阻塞等待,可以先去做自己的事,让内核缓冲区准备好了,再调用read()函数。之后还是要等待系统把数据从内核态拷贝到,这个过程是需要等待的。
而异步是「内核数据准备好」和「数据从内核态拷贝到用户态」这两个过程都不用等待。
应用程序向系统发出获取数据请求后,就立即返回,可以去做自己的事;
系统会在内核数据准备好后调用read(),并自动将数据从内核空间拷贝到用户空间,这两个过程都不用等待。
以前的想法:只有这个 内核数据准备好 过程,就区分不了非阻塞和异步。
以前的认为内核数据准备好了之后,就可以读取,而读取是不用时间的,这是错误的。
读取数据这个过程是内核把数据从内核态拷贝到用户态,这是需要时间的,在这一步骤需要等待的都是同步I/O。(主动去调用read()函数都是同步I/O,因为需要等待内核把数据从内核态拷贝到用户态)
这样就可以清楚意识到I/O多路复用是同步I/O,的因为需要应用程序主动调用read(),需要等待内核把数据从内核态拷贝到用户态。
再做个比喻:取快递。
也有两个过程:
1.快递已到达家附近的快递站(对应内核数据准备好)
2.快递到家(对应数据从内核态拷贝到用户态)
非阻塞:
你不用去频繁问快递是否到了没,快递到了,快递小哥会通知你,你就要到快递站拿,所以第二个过程还是需要你去操作,这就对应了需要等待内核把数据从内核态拷贝到用户态。
异步:
你想要取快递,发出请求,接着就可以做自己的事了。之后快递小哥会把快递放到快递站(内核数据准备好),接着把快递送到你家(数据从内核态拷贝到用户态),这两个过程你都不用等待,不用自己去操作。
总结:
清楚知道是有两个过程的(1.等待内核缓冲区数据就绪,2.将数据从内核态拷贝到用户态)