在此感谢前辈们指导,此处是我自己的理解,部分图片和段落来源于http://www.cnblogs.com/alex3714/articles/5876749.html

http://www.cnblogs.com/Anker/p/3254269.html

如果在学习过程中遇到了问题,请咨询:2775724349(因为自己时间有限,所以可能不会常回复,但会收集每个星期大家所遇到的问题,在周六以博文形式在博客中发表)

阻塞 I/O(blocking IO)

python--->io模式详解(适合零基础)_python

python--->io模式详解(适合零基础)_python_02

当进程开始read想读取数据时,用recv函数从内存中取数据,但是呢,内存中的数据,没有准备好,怎么办呢,这个时候就不断地开始等待,等到数据准备好后,就会结束阻塞状态,开始拷贝数据,然后发送给用户。

一个粗略的比方:我和女票出去逛街培养感情。顺便先去餐厅吃个饭

(1)我和女友点完餐后,不知道什么时候能做好,只好坐在餐厅里面等,直到做好,然后吃完才离开。

女友本想还和我一起逛街的,但是不知道饭能什么时候做好,只好和我一起在餐厅等,而不能去逛街,直到吃完饭才能去逛街,中间等待做饭的时间浪费掉了。这就是典型的阻塞

一句话来讲;

blocking IO的特点就是在IO执行的两个阶段都被block了。

非阻塞 I/O(nonblocking IO)

python--->io模式详解(适合零基础)_python_03

python--->io模式详解(适合零基础)_python_04

当一个用户想用到数据,调用recv函数时,,发消息给内存,但是内存说:大兄弟,我还没准备好。然后返回一个error(消息)给用户,但用户的系统是个急性子,心想:老大找我要啊。你也快点吧。说完,又继续发了一个消息给内核,直到数据准备好,才结束访问

比方:

(2)我女友不甘心白白在这等,又想去逛商场,又担心饭好了。所以我们逛一会,回来询问服务员饭好了没有,来来回回好多次,饭都还没吃都快累死了啦。这就是非阻塞。需要不断的询问,是否准备好了。

I/O 多路复用( IO multiplexing)

IO multiplexing就是我们说的select,poll,epoll,有些地方也称这种IO方式为event driven IO。select/epoll的好处就在于单个process就可以同时处理多个网络连接的IO。它的基本原理就是select,poll,epoll这个function会不断的轮询所负责的所有socket,当某个socket有数据到达了,就通知用户进程。

这个就开始变得复杂了,接下来我尽量说大白话。先上图:

python--->io模式详解(适合零基础)_python_05

python--->io模式详解(适合零基础)_python_06

为了增强大家的理解,我首先将第三种与前两种,进行对比

对于第一种和第二种阻塞 I/O(blocking IO):如果在单线程下采取这种方案,一收数据,就阻塞,一收数据就阻塞,那如果我要一下子收多个数据怎么办呢,那还不玩儿完,所以这时不能在多个socket下接收数据,即便后面继续来了数据,也得等着,因为前面卡住了

但是对于这一种,假如单线程下一下子向100个socket发送数据,然后在这100个socket来个for循环,等候他们发的数据,一个循环过后,接收到了5个数据,那么就开始拷贝数据,发送给用户,有人会想,那其他的了,就不会在意了,因为 ,我已经接收到了数据。

select,poll,epoll作用就是在不断地循环,进行筛选 。

再重复一遍select连接上100个socket句柄,然后内核就开始检测这100个句柄,哪怕有一个人接收到了数据,他就把数据返回

接下来,介绍一个更加牛B的io

异步 I/O(asynchronous IO)

python--->io模式详解(适合零基础)_python_07

python--->io模式详解(适合零基础)_python_08

异步io先调用函数发通知给内核,但是,内核说我没有数据,返回一个消息,然后用户就开始做其他的事了,等到内核把数据拷贝完,就把函数直接调用给用户,可能后来一点大家话是云里雾里的,用一个抽像的比方:

我和女票不是要出去吃饭吗,我们不出去吃了,直接在家里点外卖,等外卖来了,才开始吃饭,饭吃完了,就可以直接出去玩儿。,在这期间,我和女票爱干嘛干嘛,外卖都管不着,对用户造不成影响。

相当于内核帮我们等,但是我们不需要等。这个地方与三者的区别在于,前三者,在将数据准备好后,用户还需要read一下,read过程中,可能会卡,但是这个绝不会卡。

      

     non-blocking IO就是blocking IO在执行recvfrom这个system call的时候,如果kernel的数据没有准备好,这时候不会block进程。但是,当kernel中数据准备好的时候,recvfrom会将数据从kernel拷贝到用户内存中,这个时候进程是被block了,在这段时间内,进程是被block的。

     而asynchronous IO则不一样,当进程发起IO 操作之后,就直接返回再也不理睬了,直到kernel发送一个信号,告诉进程说IO完成。在这整个过程中,进程完全没有被block。

 四种图片对比

python--->io模式详解(适合零基础)_python_09

好了,就是这样了。最后一种最牛B,