<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>

                ??碼云GVP開源項目 12k star Uniapp+ElementUI 功能強大 支持多語言、二開方便! 廣告
                [TOC] ## 概述 在網絡上看到很多關于阻塞IO、非阻塞IO、同步IO、異步IO的例子,總覺得寫的過于復雜并且讓人難以理解。于是我把我自己把這幾個概念的理解寫下來以供參考。 ## POSIX POSIX(可移植操作系統接口)把同步IO操作定義為導致進程阻塞直到IO完成的操作,反之則是異步IO I/O 操作一般分為兩個部分: * 階段1:應用程序發起 I/O 操作請求,**等待數據**,或者將要操作的數據拷貝到系統內核中(比如 socket)。 * 階段2:系統內核進行 I/O 操作(一般是內核將數據拷貝到用戶進程中)。 ## 簡述阻塞、非阻塞、同步、異步 ### 阻塞和非阻塞 阻塞和非阻塞發生在請求處,也就是**階段1** ,關注的是程序在等待調用結果時的狀態。 * 阻塞是指**調用結果**返回之前,當前進程(線程)會被掛起,調用進程(線程)會阻塞在IO請求處,直到IO操作請求完成,數據到來,最重要的是用戶進程的函數在請求過程中不會返回。 * ![](http://image.euphie.net/2017-09-24-23-18-01.png) * eg:recv()函數默認是阻塞的,什么是阻塞呢?就是當你調用recv()函數時,整個進程或者線程就等待在這里了,直到你recv的fd的所有信息都被send過來,這么做好處就是保證所有信息都能夠完整的讀取了,但劣勢也很明顯,就是在recv()的過程中你的進程或線程做不了其它事情,由此,引入了非阻塞IO。 * 非阻塞調用是指在不能立刻得到結果之前,該調用不會阻塞進程(線程),進程(線程)可以去干別的事情,一般使用輪詢的方法來查詢IO操作的數據是否準備好了。 * ![](http://image.euphie.net/2017-09-24-23-19-53.png) * eg:以recv()函數為例,當你將其設置為非阻塞時,每次當你recv()時,就直接返回,不管信息有沒有完全send進來,好處很明顯,recv()了之后進程馬上能處理下一行代碼,壞處也很明顯,就是你不知道你的消息是否讀完了,這種問題就是TCP中大名鼎鼎的半包問題(解決辦法主要是通過一個buffer緩存所有讀進來的消息) * 當使用**I/O 多路復用**的時候,用戶的 I/O 操作會立即返回,但會利用 select 和 epoll 等方法對所監視的 I/O 操作描述符進行遍歷輪詢(此操作是為了檢查數據是否準備完畢,也就是 I/O 操作的**階段1**,同時此操作是阻塞,進程或者線程需要等待輪詢結果的返回),查看可用的句柄并返回。然后用戶進程再對其進行操作。 ### 同步/異步IO * 同步和異步關注的是消息通信機制,具體來說就是調用者是否等待調用結果的返回,對于 I/O 操作而言,就是應用程序是否等待 I/O 操作完成。 * eg: 以recv()函數為例, 不管 是否設置為阻塞還是非阻塞(階段1),都有一個將內核數據拷貝到用戶進程的I/O操作(階段2),如果用戶進程等待I/O操作返回,則為同步,反之則為異步。 ### 同異步io和阻塞非阻塞io的區別 結合前面的概念,可以看出,其實這兩者存在本質的區別,**它們的修飾對象是不同的**。 * 阻塞和非阻塞是指進程訪問的數據如果尚未就緒,進程是否需要等待,簡單說這相當于函數內部的實現區別,也就是未就緒時是直接返回還是等待就緒。 * 同步和異步是指訪問數據的機制,**同步一般指主動請求并等待 I/O 操作完畢的方式,當數據就緒后在讀寫的時候必須等待**,**異步則指主動請求數據后便可以繼續處理其它任務,隨后等待 I/O,操作完畢的通知,這可以使進程在數據讀寫時也不阻塞。** >**只有同步的時候,才會有是否阻塞之說**。 ## IO多路復用 這里在調用`recv`前先調用`select`或者`poll`,這兩個個系統調用都可以在內核準備好數據(網絡數據到達內核)時告知用戶進程,這個時候再調用`recv`一定是有數據的。因此這一過程中它是**阻塞于**`select`或`poll`,而沒有阻塞于`recv`,有人將非阻塞IO定義成在讀寫操作時沒有阻塞于系統調用的IO操作(不包括數據從內核復制到用戶空間時的阻塞,因為這相對于網絡IO來說確實很短暫),如果按這樣理解,這種IO模型也能稱之為非阻塞IO模型,但是按POSIX來看,它也是同步IO,稱之為同步非阻塞IO。 這種IO模型比較特別,分個段。因為它能同時監聽多個文件描述符(fd)。當有文件描述符有就緒事件時,則返回就緒事件的文件描述符來進行讀寫。 ![](http://image.euphie.net/2017-09-24-23-21-54.png) ## 異步 調用`aio_read`,讓內核等數據準備好,并且復制到用戶進程空間后執行事先指定好的函數。整個過程沒有`recv`,這才是真正的異步IO。 ![](http://image.euphie.net/2017-09-24-23-23-36.png) ## 信號驅動 通過調用sigaction注冊信號函數,等內核數據準備好的時候系統中斷當前程序,執行信號函數(在這里面調用recv)。是不是很像異步IO?很遺憾,它還是同步IO(省不了數據從內核拷貝到用戶空間的操作)。 ![](http://image.euphie.net/2017-09-24-23-22-38.png) ## 總結比較下五種IO模型 ![](https://images2015.cnblogs.com/blog/1066890/201611/1066890-20161129014959615-1351089676.png) ## 總結 IO分兩階段: ``` 1.數據準備階段 2.內核空間復制回用戶進程緩沖區階段 ``` 一般來講:阻塞IO模型、非阻塞IO模型、IO復用模型(select/poll/epoll)、信號驅動IO模型都屬于同步IO,因為階段2是阻塞的(盡管時間很短)。只有異步IO模型是符合POSIX異步IO操作含義的,不管在階段1還是階段2都可以干別的事。 >ps:以上圖片均截自UNIX網絡編程卷1。
                  <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>

                              哎呀哎呀视频在线观看