python--->io模式詳解(適合零基礎)
在此感謝前輩們指導,此處是我自己的理解,部分圖片和段落來源於http://www.cnblogs.com/alex3714/articles/5876749.html
http://www.cnblogs.com/Anker/p/3254269.html
如果在學習過程中遇到了問題,請咨詢:2775724349(因為自己時間有限,所以可能不會常回復,但會收集每個星期大家所遇到的問題,在周六以博文形式在博客中發表)
阻塞 I/O(blocking IO)
當進程開始read想讀取數據時,用recv函數從內存中取數據,但是呢,內存中的數據,沒有準備好,怎麽辦呢,這個時候就不斷地開始等待,等到數據準備好後,就會結束阻塞狀態,開始拷貝數據,然後發送給用戶。
一個粗略的比方:我和女票出去逛街培養感情。順便先去餐廳吃個飯
(1)我和女友點完餐後,不知道什麽時候能做好,只好坐在餐廳裏面等,直到做好,然後吃完才離開。
女友本想還和我一起逛街的,但是不知道飯能什麽時候做好,只好和我一起在餐廳等,而不能去逛街,直到吃完飯才能去逛街,中間等待做飯的時間浪費掉了。這就是典型的阻塞
一句話來講;
blocking IO的特點就是在IO執行的兩個階段都被block了。
非阻塞 I/O(nonblocking IO)
當一個用戶想用到數據,調用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有數據到達了,就通知用戶進程。
這個就開始變得復雜了,接下來我盡量說大白話。先上圖:
為了增強大家的理解,我首先將第三種與前兩種,進行對比
對於第一種和第二種阻塞 I/O(blocking IO):如果在單線程下采取這種方案,一收數據,就阻塞,一收數據就阻塞,那如果我要一下子收多個數據怎麽辦呢,那還不玩兒完,所以這時不能在多個socket下接收數據,即便後面繼續來了數據,也得等著,因為前面卡住了
但是對於這一種,假如單線程下一下子向100個socket發送數據,然後在這100個socket來個for循環,等候他們發的數據,一個循環過後,接收到了5個數據,那麽就開始拷貝數據,發送給用戶,有人會想,那其他的了,就不會在意了,因為 ,我已經接收到了數據。
select,poll,epoll作用就是在不斷地循環,進行篩選 。
再重復一遍select連接上100個socket句柄,然後內核就開始檢測這100個句柄,哪怕有一個人接收到了數據,他就把數據返回
接下來,介紹一個更加牛B的io
異步 I/O(asynchronous IO)
異步io先調用函數發通知給內核,但是,內核說我沒有數據,返回一個消息,然後用戶就開始做其他的事了,等到內核把數據拷貝完,就把函數直接調用給用戶,可能後來一點大家話是雲裏霧裏的,用一個抽像的比方:
我和女票不是要出去吃飯嗎,我們不出去吃了,直接在家裏點外賣,等外賣來了,才開始吃飯,飯吃完了,就可以直接出去玩兒。,在這期間,我和女票愛幹嘛幹嘛,外賣都管不著,對用戶造不成影響。
相當於內核幫我們等,但是我們不需要等。這個地方與三者的區別在於,前三者,在將數據準備好後,用戶還需要read一下,read過程中,可能會卡,但是這個絕不會卡。
non-blocking IO就是blocking IO在執行recvfrom這個system call的時候,如果kernel的數據沒有準備好,這時候不會block進程。但是,當kernel中數據準備好的時候,recvfrom會將數據從kernel拷貝到用戶內存中,這個時候進程是被block了,在這段時間內,進程是被block的。
而asynchronous IO則不一樣,當進程發起IO 操作之後,就直接返回再也不理睬了,直到kernel發送一個信號,告訴進程說IO完成。在這整個過程中,進程完全沒有被block。
四種圖片對比
好了,就是這樣了。最後一種最牛B,
python--->io模式詳解(適合零基礎)