IO 同步,非同步,阻塞,非阻塞

2021-08-24 20:39:41 字數 2844 閱讀 3264

參考文章:

好文推薦:

唉最近真是高產似母豬,剛進新公司工作量暫時不飽和,只能每天學學學學學學查漏補缺啦,學習使我快樂哈哈哈哈哈哈哈哈

標題裡的詞彙相信都經常看到,但是能說清楚的估計20個人裡面能有1個就不錯了,網上的資料也是五花八門,大部分描述差不多,很多時候估計作者本身也是似懂非懂,我也看了很多文章,抬頭的參考是寫的最清楚的,這篇文章的博主也曾有過錯誤的理解,這一篇是糾正篇,果然寫得很清晰。

同樣的,整理並加上自己的理解寫在這裡。

i/o就是輸入和輸出,核心是i/o流,流用於讀寫裝置上的資料,包括硬碟檔案、網路等

我們寫的**都是執行在使用者程序/執行緒中的,要讀寫硬碟或網路資料無法直接操作,而要通過核心,寫資料時把資料寫到核心,核心再寫到硬碟或者通過網路發出去,讀資料時,資料也是先到核心,**再從核心中把資料讀到使用者執行緒

總結:io發生時涉及的物件和步驟。

對於乙個網路io (以read舉例),涉及到兩個系統物件,乙個是呼叫這個io的使用者程序(或執行緒),另乙個就是系統核心(kernel)。當乙個read操作發生時,它會經歷兩個階段:

1. 等待資料準備 (waiting for the data to be ready)

2. 將資料從核心拷貝到程序中 (copying the data from the kernel to the process)

記住這兩點很重要,因為這些各個io模型的區別就是在兩個階段上各有不同的情況。

下面分別介紹常見的:

中文英文

阻塞io

blocking io

非阻塞io

nonblocking io

io多路復用

io multiplexing

非同步io

asynchronous io

當使用者要讀取網路資料時,就開始了第乙個階段:核心準備資料。

對於網路io來說,很多時候資料在使用者呼叫方法時還沒有完全到達(比如,還沒有收到乙個完整的udp包),這個時候核心就要等待資料完整到達。使用者程序此時會被阻塞。

當核心中資料完整到達了,進入第二階段,使用者程序/執行緒就會將資料從核心拷貝到使用者記憶體,然後核心返回結果,使用者程序才解除block的狀態,繼續執行。

所以,blocking io的特點就是在io執行的兩個階段都被block了。

當使用者程序發出read操作時,如果kernel中的資料還沒有準備好,那麼它並不會block使用者程序,而是立刻返回乙個error。從使用者程序角度講 ,它發起乙個read操作後,並不需要等待,而是馬上就得到了乙個結果。使用者程序判斷結果是乙個error時,它就知道資料還沒有準備好,於是它可以再次傳送read操作。一旦kernel中的資料準備好了,並且又再次收到了使用者程序的read,那麼核心馬上就將資料拷貝到使用者記憶體,然後返回結果。

所以,使用者程序其實是需要不斷的主動詢問kernel資料好了沒有,也叫輪詢io,特點是第一階段不阻塞,第二階段阻塞,並不是完完全全的非阻塞

select/epoll的好處就在於單個process就可以同時處理多個網路連線的io。它的基本原理就是select/epoll方法會阻塞使用者執行緒,然後核心會不斷的輪詢所負責的所有socket,一旦發現程序指定的乙個或者多個socket可以讀寫資料了,它就通知該程序,然後程序讀寫資料繼續執行。

也就是說使用者的讀寫請求會被select方法全部hold住,整個過程還是阻塞的,只是原來是被核心hold住,現在是被select擋住。

好處是原來乙個程序/執行緒只能處理乙個連線,那麼這個連線阻塞的時間就被浪費了,多路復用把這些時間用來服務別的connection了。

2019-10-31補充

以下完全個人理解,不確保正確:多路復用最大的好處是減少了執行緒數,在阻塞和非阻塞io下,每個網路連線(拿web應用伺服器來說)都需要乙個執行緒去盯著它,不管是阻塞等待,還是非阻塞定期輪訓。但是多路復用只需要乙個執行緒盯著就好了,就是每過來乙個io讀請求或者io寫請求,直接告訴核心我要做這個事情,核心幫這個執行緒盯著,再來乙個再告訴核心,核心繼續盯著,核心會去輪訓看哪些io準備好了,然後告訴這個盯著的執行緒,執行緒再繼續接下去的工作(可能是安排別的執行緒繼續)

從使用者程序角度,當它發起read操作之後,立刻就可以開始去做其它的事。

從kernel的角度,當它受到乙個asynchronous read之後,首先它會立刻返回,所以不會對使用者程序產生任何block。然後,kernel會等待資料準備完成,然後將資料拷貝到使用者記憶體,當這一切都完成之後,kernel會給使用者程序傳送乙個signal,告訴它read操作完成了。

可以看出核心幹了所有事情

原博說linux下的非同步io其實用得很少,我也沒想出這種io要怎麼利用起來。

好了,介紹完畢,看到這裡細心的小夥伴應該發現了,介紹了阻塞非阻塞非同步,那同步io去哪了,其實同步io就是代表會阻塞的io,也就是包含了上面介紹的阻塞非阻塞多路復用三種,感覺要瘋了,代表會阻塞的io,卻包含了非阻塞io,再回過頭去看看非阻塞io的總結部分,它其實不是完完全全的阻塞,而是第一階段不阻塞,第二階段阻塞,所以它也屬於同步io,多路復用也是類似。而非同步io一定是非阻塞的,都非同步了,本來兩個會被阻塞的階段都被核心做了,而且做好了會通知你,再阻塞有啥意義呢?所以我們不去討論非同步阻塞和非阻塞

完畢,感覺清晰多了,希望不會過段時間發現又有問題(╯‵□′)╯︵┻━┻

同步 非同步 阻塞 非阻塞 I O

一 同步 非同步 首先要是多個事物,只有乙個事物,是不存在同步或非同步的。同步 指協同步調。即,多個事物不能同時進行,必須乙個乙個的來,上乙個事物結束後,下乙個事物才開始。那當乙個事物正在進行時,其他事物在幹嘛呢?嚴格來講並沒有要求,但一般都處於 等待 狀態,因為後面事物的正常進行都需要依賴前面事物...

同步非同步IO,阻塞非阻塞

同步io操作 導致請求程序阻塞,知道io操作完成。非同步io操作 不導致程序阻塞。在處理 網路 io 的時候,阻塞和非阻塞都是同步io,阻塞,就是呼叫我 函式 我 函式 沒有接收完資料或者沒有得到結果之前,我不會返回。非阻塞,就是呼叫我 函式 我 函式 立即返回,通過select通知呼叫者 阻塞與非...

同步IO 非同步IO 阻塞IO 非阻塞IO

同步io 非同步io 阻塞io 非阻塞io,這幾個詞常見於各種各樣的與網路相關的文章之中,往往不同上下文中它們的意思是不一樣的,以致於我在很長一段時間對此感到困惑,所以想寫一篇文章整理一下。posix 可移植作業系統介面 把同步io操作定義為導致程序阻塞直到io完成的操作,反之則是非同步io按pos...