• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            jianlinzhang

              C++博客 :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理 ::
              16 隨筆 :: 2 文章 :: 17 評論 :: 0 Trackbacks

             IO - 同步,異步,阻塞,非阻塞
            同步(synchronous) IO和異步(asynchronous) IO,阻塞(blocking) IO和非阻塞(non-blocking)IO ,我相信這幾個詞困擾過很多人,更痛苦的是,如果你查閱過文獻資料,你會發現不同的資料中的解釋是不一樣的,例如在wiki中,異步和非阻塞被當成了一個概念 。
            出現這種情況的原因,我認為很大程度上是因為IO這個概念本身就很寬泛,它其實包含了好幾個層面。比如說,你可以把它看做是一個物理上的設備,也可以看做是 OS抽象出來的一個軟件,還可以看做是平時寫程序用的read(),write()函數,不同的層面對于這幾個詞的理解也是不一樣的。

            先看一個較低的層次。如果從CPU的角度看,其實大部分的IO都是異步的:因為CPU啟動這個IO操作后,就去干其它的事情了,一直到產生一個中斷,告訴它IO完成了。
            “Most physical I/O is asynchronous—the CPU starts the transfer and goes off to do something else until the interrupt arrives. User programs are much easier to write if the I/O operations are blocking—after a read system call the program is automatically suspended until the data are available in the buffer. It is up to the operating system to make operations that are actually interrupt-driven look blocking to the user programs.” (引自 Modern Operating Systems, 2ed)

            不過,本文并不想探究那么底層的東東。作為程序員,更多的還是從應用層面來考慮。所以,以下重點介紹的是應用程序中能夠采用的四種IO機制。
            (說明,下文中圖片引用自 http://www.ibm.com/developerworks/cn/linux/l-async/

            首先,從最常用到的,也是最容易理解的同步阻塞IO 說起。

            在這個模型中,應用程序(application)為了執行這個read操作,會調用相應的一個system call,將系統控制權交給kernel,然后就進行等待(這其實就是被阻塞了)。kernel開始執行這個system call,執行完畢后會向應用程序返回響應,應用程序得到響應后,就不再阻塞,并進行后面的工作。
             

             
            例如,“在調用 read 系統調用時,應用程序會阻塞并對內核進行上下文切換。然后會觸發讀操作,當響應返回時(從我們正在從中讀取的設備中返回),數據就被移動到用戶空間的緩沖區中。然后應用程序就會解除阻塞(read 調用返回)。”


             舉一個淺顯的例子,就好比你去一個銀行柜臺存錢。首先,你會將存錢的單子填好,然后交給柜員。這里,你就好比是application,單子就是調用的 system call,柜員就是kernel。提交好單子后,你就坐在柜臺前等,相當于開始進行等待。柜員辦好以后會給你一個回執,表示辦好了,這就是 response。然后你就可以拿著回執干其它的事了。注意,這個時候,如果你辦完之后馬上去查賬,存的錢已經打到你的賬戶上了。后面你會發現,這點很重要。

            接下來談同步非阻塞IO 。
            先看這個圖,

             

            在linux下,應用程序可以通過設置文件描述符的屬性O_NONBLOCK,I/O操作可以立即返回,但是并不保證I/O操作成功。
            也就是說,當應用程序設置了O_NONBLOCK之后,執行write操作,調用相應的system call,這個system call會從內核中立即返回。但是在這個返回的時間點,數據可能還沒有被真正的寫入到指定的地方。也就是說,kernel只是很快的返回了這個 system call(這樣,應用程序不會被這個IO操作blocking),但是這個system call具體要執行的事情(寫數據)可能并沒有完成。而對于應用程序,雖然這個IO操作很快就返回了,但是它并不知道這個IO操作是否真的成功了,如果想知道,需要應用程序主動地去問kernel。

            這次不是去銀行存錢,而是去銀行匯款。同樣的,你也需要填寫匯款單然后交給柜員,柜員進行一些簡單的手續處理就能夠給你回執。但是,你拿到回執并不意味著錢已經打到了對方的賬上。事實上,一般匯款的周期大概是24個小時,如果你要以存錢的模式來匯款的話,意味著你需要在銀行等24個小時,這顯然是不現實的。所以,同步非阻塞IO在實際生活中也是有它的意義的。

            再來談談異步阻塞IO 。
            在linux中,常常通過select/poll來實現這種機制。

             
            以圖為例,
            和之前一樣,應用程序要執行read操作,因此調用一個system call,這個system call被傳遞給了kernel。但在應用程序這邊,它調用system call之后,并不等待kernel返回response,這一點是和前面兩種機制不一樣的地方。這也是為什么它被稱為異步的原因。但是為什么稱其為阻塞呢?這是因為雖然應用程序是一個異步的方式,但是select()函數會將應用程序阻塞住,一直等到這個system call有結果返回了,再通知應用程序。也就是說,“在這種模型中,配置的是非阻塞 I/O,然后使用阻塞 select 系統調用來確定一個 I/O 描述符何時有操作。”
            所以,從IO操作的實際效果來看,異步阻塞IO和第一種同步阻塞IO是一樣的,應用程序都是一直等到IO操作成功之后(數據已經被寫入或者讀取),才開始進行下面的工作。異步阻塞IO的好處在于一個select函數可以為多個描述符提供通知,提高了并發性。


            關于提高并發性這點,我們還以銀行為例說明。比如說一個銀行柜臺,現在有10個人想存錢。按照現在銀行的做法,一個個排隊。第一個人先填存款單,然后提交,然后柜員處理,然后給回執,成功后再輪到下一個人。大家應該都在銀行排過對,這樣的流程是很痛苦的。如果按照異步阻塞的機制,10個人都填好存款單,然后都提交給柜臺,提交完之后所有的10個人就在銀行大廳等待。這時候會專門有個人,他會了解存款單處理的情況,一旦有存款單處理完畢,他會將回執交給相應的正在大廳等待的人,這個拿到回執的人就可以去干其他的事情了。而前面提到的這個專人,就對應于select函數。

            最后,談談異步非阻塞IO 。
            這個概念相對前面兩個反而更容易理解一些。

             
            如圖所示,應用程序提交read請求的system call,然后,kernel開始處理相應的IO操作,而同時,應用程序并不等kernel返回響應,就會開始執行其他的處理操作(應用程序沒有被IO操作所阻塞)。當kernel執行完畢,返回read的響應,就會產生一個信號或執行一個基于線程的回調函數來完成這次 I/O 處理過程。


            比如銀行存錢。現在某銀行新開通了一項存錢業務。用戶之需要將存款單交給柜臺,然后無需等待就可以離開了。柜臺辦好以后會給用戶發送一條短信,告知交易成功。這樣用戶不需要在柜臺前進行長時間的等待,同時,也能夠得到確切的消息知道交易完成。


            從前面的介紹中可以看出,所謂的同步和異步,在這里指的是application和kernel之間的交互方式。如果application不需要等待 kernel的回應,那么它就是異步的。如果application提交完IO請求后,需要等待“回執”,那么它就是同步的。
            而阻塞和非阻塞,指的是application是否等待IO操作的完成。如果application必須等到IO操作實際完成以后再執行下面的操作,那么它是阻塞的。反之,如果不等待IO操作的完成就開始執行其它操作,那么它是非阻塞的。

             

            本文來自CSDN博客,轉載請標明出處:http://blog.csdn.net/historyasamirror/archive/2009/06/15/4270633.aspx

            posted on 2009-07-10 17:30 張建林 閱讀(598) 評論(0)  編輯 收藏 引用
            久久午夜无码鲁丝片秋霞 | 久久久久一级精品亚洲国产成人综合AV区 | 色综合久久久久久久久五月| 国产激情久久久久影院| 97精品依人久久久大香线蕉97| 久久精品国产一区二区三区日韩| 亚洲精品无码专区久久久| 欧洲精品久久久av无码电影| 精品久久久久久无码专区| 国内精品久久人妻互换| 精品久久久久久无码中文字幕一区| 亚洲AV日韩精品久久久久久久| 精品久久久久成人码免费动漫| 亚洲欧美久久久久9999| 香蕉久久影院| 少妇精品久久久一区二区三区| 2021精品国产综合久久| 久久亚洲国产欧洲精品一| 国产成人久久久精品二区三区| 久久国产乱子伦精品免费强 | 久久久久久青草大香综合精品| 久久中文字幕人妻熟av女| 91精品国产91久久久久久青草 | 日产精品久久久一区二区| 久久久久99精品成人片欧美 | 国产精品久久国产精品99盘| 四虎久久影院| 久久男人AV资源网站| 无码人妻久久一区二区三区免费丨 | 久久免费香蕉视频| 蜜桃麻豆www久久| 久久99国产乱子伦精品免费| 久久久亚洲AV波多野结衣 | 99久久超碰中文字幕伊人| 国色天香久久久久久久小说| 久久久久亚洲AV无码专区桃色| 国产成人无码久久久精品一| 色欲久久久天天天综合网| 亚洲精品白浆高清久久久久久| 精品一二三区久久aaa片| 亚洲精品无码专区久久久|