• <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++博客 :: 首頁 :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理 ::
              16 隨筆 :: 2 文章 :: 17 評論 :: 0 Trackbacks

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

            先看一個較低的層次。如果從CPU的角度看,其實大部分的IO都是異步的:因為CPU啟動這個IO操作后,就去干其它的事情了,一直到產(chǎn)生一個中斷,告訴它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)

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

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

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

             
            例如,“在調(diào)用 read 系統(tǒng)調(diào)用時,應(yīng)用程序會阻塞并對內(nèi)核進行上下文切換。然后會觸發(fā)讀操作,當(dāng)響應(yīng)返回時(從我們正在從中讀取的設(shè)備中返回),數(shù)據(jù)就被移動到用戶空間的緩沖區(qū)中。然后應(yīng)用程序就會解除阻塞(read 調(diào)用返回)。”


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

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

             

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

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

            再來談?wù)劗惒阶枞鸌O 。
            在linux中,常常通過select/poll來實現(xiàn)這種機制。

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


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

            最后,談?wù)劗惒椒亲枞鸌O 。
            這個概念相對前面兩個反而更容易理解一些。

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


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


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

             

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

            posted on 2009-07-10 17:30 張建林 閱讀(602) 評論(0)  編輯 收藏 引用

            只有注冊用戶登錄后才能發(fā)表評論。
            網(wǎng)站導(dǎo)航: 博客園   IT新聞   BlogJava   博問   Chat2DB   管理


            无码专区久久综合久中文字幕| 久久天天躁狠狠躁夜夜avapp | 久久久久久久人妻无码中文字幕爆| 热RE99久久精品国产66热| 模特私拍国产精品久久| 色综合久久久久久久久五月| 18岁日韩内射颜射午夜久久成人| 亚洲国产精品无码久久久久久曰| 久久久久久久久久久久中文字幕| 91久久成人免费| 亚洲va久久久噜噜噜久久男同| 97精品国产97久久久久久免费| 人妻系列无码专区久久五月天| 精品久久久久久久无码| 理论片午午伦夜理片久久| 久久无码人妻一区二区三区午夜| 久久久久久久亚洲精品| …久久精品99久久香蕉国产| 亚洲国产成人精品女人久久久| 久久久噜噜噜久久中文福利| 国产精品成人久久久| 亚洲国产精品一区二区久久| 色欲综合久久中文字幕网| 青青草国产97免久久费观看| 91性高湖久久久久| 成人久久综合网| 精品久久久久久成人AV| 久久久久国产精品人妻| 欧美日韩精品久久久免费观看| 99久久这里只有精品| 精品无码久久久久久尤物| 久久久国产乱子伦精品作者| 久久九九精品99国产精品| 日韩久久久久久中文人妻| 中文字幕无码精品亚洲资源网久久| 伊人久久大香线蕉无码麻豆| 欧美久久亚洲精品| 亚洲精品国产综合久久一线| 久久精品中文字幕大胸| 性欧美丰满熟妇XXXX性久久久 | 国产一区二区三精品久久久无广告 |