java --- BIO NIO AIO

概述

      本文將會介紹 unix 系統中 IO 的 5 種模式,在後續的文章後會介紹 reactor 和 Proactor 兩種IO模式。php

異步和阻塞

       咱們先來大概瞭解了一下異步和阻塞的問題。 能夠查看一下兩個連接 : html

https://www.zhihu.com/question/19732473/answer/20851256java

https://www.zhihu.com/question/19732473/answer/14413599react

 

阻塞非阻塞: 請求不能當即獲得應答,須要等待,那就是阻塞;不然能夠理解爲非阻塞。 多線程

同步異步: 某業務須要甲乙甚至多方合做的時候, 併發

  1. 老是按照「甲方請求一次,乙方應答一次」這樣的有序序列處理業務,只有當「一次請求一次應答」的過程結束才能夠發生下一次的「一次請求一次應答」,那麼就說他們採用的是同步。(同步IO中對同一個描述符的操做必須是有序的
  2. 若是甲方只要有須要,就會發送請求,無論上次請求有沒有獲得乙方應答。而乙方只要甲方有請求就會接受,不是等此次請求處理完畢再接受甲方新請求。這樣請求應答分開的序列,就能夠認爲是異步。異步狀況下,請求和應答不須要一致進行,可能甲方後請求的業務,卻先獲得乙方的應答。同步是線性的,而異步能夠認爲是併發的。(異步IO中,異步IO能夠容許多方同時對同一個描述符發送IO請求,或者一次發多個請求,固然有機制保證如何區分這些請求,

做者:Shihui wang
連接:https://www.zhihu.com/question/19732473/answer/14413599異步

       能夠這樣理解 : 同步異步關注的是協做方式,而阻塞和非阻塞則是遇到IO操做時,請求者當時的狀態。async

 

5種 IO 模式       

        UNIX 5種IO 模式,分別是 函數

  • blocking IO   阻塞IO
  • non-blocking IO  非阻塞IO 
  • io multiplexing  多路複用IO
  • asynchronous IO  異步IO
     

       因爲signal driven IO在實際中並不經常使用,因此我這隻說起剩下的四種IO Model。瞭解4種模式以前咱們須要注意這些知識點。學習

 

  IO發生時涉及的對象和步驟。

       對於一個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)

 

線程數量

       同時咱們還須要知道一點,對於請求,是否是建立越多的線程就越好呢?建立的線程應該和底層機器能夠承受的線程數量有關,具體的能夠看這篇文章,多個請求對應太多的線程有可能會致使太多的內存開銷和時間分片,多個線程會致使CPU 切換線程帶來的開銷,咱們學習計算機操做系統知道當切換線程時須要從新將以前線程執行的信息從新加載到主存中,可是有可能因爲緩衝機制(例如LRU)將會淘汰掉某些信息,信息的加載將會帶來時間開銷。

     

blocking IO

       阻塞 IO ,能夠用下面的圖來表示 :

 

blockingIO

       能夠看到 process 進程一直阻塞在調用 recvfrom 以後,一直到內核返回 ok .

 

non-blocking IO 

       從圖中能夠看出,當用戶進程發出read操做時,若是kernel中的數據尚未準備好,那麼它並不會block用戶進程,而是馬上返回一個error。從用戶進程角度講 ,它發起一個read操做後,並不須要等待,而是立刻就獲得了一個結果。用戶進程判斷結果是一個error時,它就知道數據尚未準備好,因而它能夠再次發送read操做。一旦kernel中的數據準備好了,而且又再次收到了用戶進程的system call,那麼它立刻就將數據拷貝到了用戶內存,而後返回。
       因此,用戶進程實際上是須要不斷的主動詢問kernel數據好了沒有
non-blocking

 

IO multiplexing

       多路複用 IO , 它將會首先調用select 函數,當數據沒準備好,進程依舊會被阻塞,當內核數據準備好,它會通知一下用戶進程,用戶進程調用 recvfrom 函數,進入第二次阻塞,等內核將數據成功拷貝到用戶進程的時候,用戶進程成功返回。過程以下 :

 

mult

       能夠知道,多路複用會比以前的模式多了一次函數調用,上面咱們也可使用 多線程+ 阻塞IO 的方式來實現,那麼多路複用這種方式又在哪裏呢?使用select能夠處理更多的connection, select/epoll的優點並非對於單個鏈接能處理得更快,而是在於能處理更多的鏈接。實際中咱們會使用 non-blocking  + 多路複用,這樣輪詢是否有事件到來的請求就交給 select 來完成就能夠了。

 

Asynchronous I/O

        用戶進程發起read操做以後,馬上就能夠開始去作其它的事。而另外一方面,從kernel的角度,當它受到一個asynchronous read以後,首先它會馬上返回,因此不會對用戶進程產生任何block。而後,kernel會等待數據準備完成,而後將數據拷貝到用戶內存,當這一切都完成以後,kernel會給用戶進程發送一個signal,告訴它read操做完成了。

asynose

 

總結

       這篇文章,咱們知道了阻塞與非阻塞,異步同步之間的區別,瞭解了5中 IO 模式,在後續的文章咱們會深刻Reator 模式和java NIO實現。

 

參考資料

相關文章
相關標籤/搜索