<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                合規國際互聯網加速 OSASE為企業客戶提供高速穩定SD-WAN國際加速解決方案。 廣告
                [toc] ## 網絡IO的模型分類 此IO模型出至Richard Stevens的<<UNIX? Network Programming Volume 1>> Stevens在文章中一共比較了五種IO Model: * blocking IO 阻塞IO * nonblocking IO 非阻塞IO * IO multiplexing IO多路復用 * signal driven IO 型號驅動IO * asynchronous IO 異步IO >由signal driven IO(信號驅動IO)在實際中并不常用,所以主要介紹其余四種IO Model。 對于一個network IO (以read舉例),它會涉及到兩個系統對象,一個是調用這個IO的process (or thread),另一個就是系統內核(kernel)。當一個read操作發生時,該操作會經歷兩個階段: ~~~ 1)等待數據準備 (Waiting for the data to be ready) 2)將數據從內核拷貝到進程中(Copying the data from the kernel to the process) ~~~ 這兩點很重要,因為這些IO模型的區別就是在兩個階段上各有不同的情況。 ## **阻塞IO(blocking IO)** 在linux中,默認情況下所有的socket都是blocking,一個典型的讀操作流程大概是這樣: ![](https://images2017.cnblogs.com/blog/827651/201801/827651-20180121220439365-1845551743.png) * 準備數據階段 當用戶進程調用了recvfrom這個系統調用,kernel就開始了IO的第一個階段:準備數據。對于network io來說,很多時候數據在一開始還沒有到達,這個時候kernel就要等待足夠的數據到來。 而在用戶進程這邊,整個進程會被阻塞。 * 拷貝數據階段 當kernel一直等到數據準備好了,它就會將數據從kernel中拷貝到用戶內存,然后kernel返回結果,用戶進程才解除block的狀態,重新運行起來。 * 總結 **blocking IO的特點就是在IO執行的兩個階段(等待數據和拷貝數據兩個階段)都被block了。** * 多線程能否解決 **對應所面臨的可能同時出現的上千甚至上萬次的客戶端請求,“線程池”或“連接池”或許可以緩解部分壓力,但是不能解決所有問題。總之,多線程模型可以方便高效的解決小規模的服務請求,但面對大規模的服務請求,多線程模型也會遇到瓶頸** 可以用非阻塞接口來嘗試解決這個問題。 ## **非阻塞IO(non-blocking IO)** Linux下,可以通過設置socket使其變為non-blocking。當對一個non-blocking socket執行讀操作時,流程是這個樣子: ![](http://book.luffycity.com/python-book/assets/chapter7/%E9%9D%9E%E9%98%BB%E5%A1%9EIO.png) * 數據準備階段 當用戶進程發出read操作時,如果kernel中的數據還沒有準備好,那么它并不會block用戶進程,而是立刻返回一個error。 從用戶進程角度講 ,它發起一個read操作后,并不需要等待,而是馬上就得到了一個結果。用戶進程判斷結果是一個error時,它就知道數據還沒有準備好,于是用戶就可以在本次到下次再發起read詢問的時間間隔內做其他事情,或者直接再次發送read操作。 * 拷貝數據階段 一旦kernel中的數據準備好了,并且又再次收到了用戶進程的system call,那么它馬上就將數據拷貝到了用戶內存(這一階段仍然是阻塞的),然后返回。 ~~~ 也就是說非阻塞的recvform系統調用調用之后,進程并沒有被阻塞, 內核馬上返回給進程,如果數據還沒準備好,此時會返回一個error。 進程在返回之后,可以干點別的事情,然后再發起recvform系統調用。 重復上面的過程,循環往復的進行recvform系統調用,這個過程通常被稱之為輪詢。 輪詢檢查內核數據,直到數據準備好,再拷貝數據到進程,進行數據處理。 需要注意,拷貝數據整個過程,進程仍然是屬于阻塞的狀態。 ~~~ * 總結 **在非阻塞式IO中,用戶進程其實是需要不斷的主動詢問kernel數據準備好了沒有。** **但是非阻塞IO模型絕不被推薦。** * 優點 能夠在等待任務完成的時間里干其他活了(包括提交其他任務,也就是 “后臺” 可以有多個任務在“”同時“”執行)。 * 缺點: 循環調用recv()將大幅度推高CPU占用率; 任務完成的響應延遲增大了,這會導致整體數據吞吐量的降低。 因為每過一段時間才去輪詢一次read操作,而任務可能在兩次輪詢之間的任意時間完成。 ## **多路復用IO(IO multiplexing)** IO multiplexing也可以說是select/epoll,也稱這種IO方式為**事件驅動IO**(event driven IO)。 select/epoll的好處就在于單個process就可以同時處理多個網絡連接的IO。它的基本原理就是select/epoll這個function會不斷的輪詢所負責的所有socket,當某個socket有數據到達了,就通知用戶進程。它的流程如圖: ![](https://images2017.cnblogs.com/blog/827651/201801/827651-20180121220750724-1438537565.png) * 數據準備階段: 當用戶進程調用了select,那么整個進程會被block,而同時,kernel會“監視”所有select負責的socket * 拷貝數據階段 當任何一個socket中的數據準備好了,select就會返回。這個時候用戶進程再調用read操作,將數據從kernel拷貝到用戶進程。 * 結論 **結論: select的優勢在于可以處理多個連接,不適用于單個連接** 用select的優勢在于它可以同時處理多個connection。 **可以使用selectors模塊,幫我們默認選擇當前平臺下最合適的IO多路復用模型** * **該模型的優點:** 相比其他模型,使用select() 的事件驅動模型只用單線程(進程)執行,占用資源少,不消耗太多 CPU,同時能夠為多客戶端提供服務。 如果試圖建立一個簡單的事件驅動的服務器程序,這個模型有一定的參考價值。* * **該模型的缺點:** 首先select()接口并不是實現“事件驅動”的最好選擇。因為當需要探測的句柄值較大時,select()接口本身需要消耗大量時間去輪詢各個句柄。 * **幾種多路復用IO的實現** select 輪詢方式,windows只支持這種方式 ,linux也支持 poll 輪詢方式,linux支持,poll能夠監聽的對象比select要多 **epoll 回調函數的方式,只有linux ,是一種很高效的方式** ## 異步IO(Asynchronous I/O) Linux下的asynchronous IO其實用得不多,從內核2.6版本才開始引入,。先看一下它的流程: ![](https://images2017.cnblogs.com/blog/827651/201801/827651-20180121220949521-1279971385.png) * 數據準備階段 用戶進程發起read操作之后,立刻就可以開始去做其它的事。而另一方面,從kernel的角度,當它受到一個asynchronous read之后,首先它會立刻返回,所以不會對用戶進程產生任何block。 * 數據準備階段 然后,kernel會等待數據準備完成,然后將數據拷貝到用戶內存,當這一切都完成之后,kernel會給用戶進程發送一個signal,告訴它read操作完成了。 * 優缺點 異步IO應該是最好的IO模型,因為它在兩個階段都沒有阻塞,但是python沒有辦法直接實現異步IO,但是可以使用開源的如`Tornado框架`等
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看