linux下的 I/O 模型,同步/非同步,阻塞/非阻塞介紹
同步/非同步,阻塞/非阻塞
一提到網路程式設計中的 I/O 模型,總會涉及到這幾個概念,但是這幾個名詞又容易混淆,於是我想總結一下。
我們先看一下在《UNIX網路程式設計:卷一》中講到的5中 UNIX 下的 I/O 模型,分別是
- 阻塞式 I/O
- 非阻塞式 I/O
- I/O 複用
- 訊號驅動式 I/O
- 非同步 I/O
五種 I/O 模型
阻塞式 I/O 模型
預設情況下,所有的套接字都是阻塞的。使用者程序執行系統呼叫 recvfrom 時,會導致應用程序阻塞,什麼也不幹,直到核心把資料準備好,並且將資料從核心複製到使用者程序,最後使用者程序再處理資料。在等待資料到處理資料的兩個階段,整個程序都被阻塞,不能做別的事情,此程序不再擁有 cpu 時間片,只是簡單的等待響應的狀態,因此從處理的角度來看,這是非常有效的。
當用戶程序呼叫 recvfrom/recv 時,核心就開始了 IO 的第一個階段,準備資料(對於網路IO 來說,很多時候資料在一開始還沒有到達。比如還沒有收到一個完整的 UDP 包,這時核心就需要等待資料到來)。資料被拷貝到核心的緩衝區是需要一個過程的。在使用者程序這裡,程序會被阻塞。第二個階段,當核心將資料準備好了,會將資料從核心拷貝到使用者程序然後核心返回結果,使用者程序解除阻塞狀態。即阻塞式 IO 在 IO 執行階段的兩個過程中都被阻塞了。
優點:能夠及時返回資料,無延時。
缺點:需要使用者程序一直處於等待狀態。
非阻塞式 IO
程序把一個套接字設定為非阻塞時,通知核心當所請求的 IO 操作非得把本程序投入睡眠狀態才能完成時,不要把程序投入睡眠,而是返回一個錯誤。也就是說非阻塞的 recvfrom 被呼叫後,程序不會被阻塞,核心馬上返回給程序,如果資料還沒有準備好,會返回一個error。程序在返回之後,可以做一些其他事情,然後再呼叫 recvfrom 。重複上述過程,迴圈的呼叫 recvfrom。這個過程通常被稱為輪詢。輪詢檢查核心資料,直到資料準備好,再拷貝資料到程序,進行資料處理。這裡需要注意一點,在拷貝資料的過程中,程序仍然處於阻塞狀態。以下為非阻塞套接字呼叫 recvfrom 時的操作
優點:可以在等待任務完成的時間內做其它事了。
缺點:任務完成的響應延遲增大了,因為沒過一段時間才會去檢查一次,而任務可能在兩次查詢之間的時刻內完成。
IO 複用
非阻塞式 IO 需要不斷主動輪詢,輪詢佔據了很大一部分過程,會消耗大量 cpu 資源,如果核心可以幫我們迴圈查詢多個任務的完成狀態,有要有任何一個任務完成,會告訴程序就好了。這就是 IO 多路複用,對應的有 select,poll,epoll 這些函式。select 輪詢相對於非阻塞式的輪詢的區別在於,select 可以等待多個 socket,能同時對多個 IO 埠進行監聽,當其中任何一個 socket 的資料準備好了,都可以知道,然後程序再進行 recvfrom 呼叫,將核心資料拷貝到使用者程序,當然這個過程是阻塞的。
IO 複用的好處就在於單個程序/執行緒就可以同時處理多個網路連線的 IO。它的基本原理就是不斷的輪詢所負責的所有 socket,當某個 socket 有資料到達時,就通知使用者程序。當用戶程序呼叫了 select,那麼整個程序會被阻塞,同時核心會監視所有 select 負責的socket,select 會在指定的時間內(由引數設定)返回準備好的 socket 的個數,這個時候使用者程序再呼叫 read 操作,資料從核心拷貝到使用者程序。
上圖和阻塞式 IO 的圖其實並沒有太大的不同,事實上,要差一些。因為這裡需要使用兩個系統呼叫,而阻塞式 IO 只使用了一個,select 的優勢在於可以同時處理多個連線。
在 IO 多路複用中,對於每一個 socket,一般設定為非阻塞的,但是,如上圖所示,使用者程序其實是一直被阻塞的,只不過是阻塞在 select 上,而不是被 socket IO 給阻塞。
訊號驅動式 IO
先註冊一個訊號處理函式,程序繼續執行並不阻塞,當資料準備好時,程序會收到一個SIGIO 訊號,可以在訊號處理函式中呼叫 IO 操作函式處理資料。
非同步 IO
呼叫類似於 aio_read 等函式之後,無論核心是否將資料準備好,此類函式都會直接返回。然後使用者態程序可以去做其他事情。等到 soecket 資料準備好了,核心直接複製資料給程序。然後從核心向程序傳送通知。
當用戶程序呼叫 aio_read 之後,立刻就可以去做其他事情,從核心來看,當它收到一個非同步呼叫之後,它會立刻返回,所以不會阻塞使用者程序。然後,核心會等待資料準備完成,然後將資料拷貝到使用者程序。然後核心會給使用者程序傳送一個訊號,或執行一個回撥函式來完成這次的 IO 處理過程,告訴使用者程序操作完成。
同步與非同步
同步和非同步這兩個概念關注的訊息的通知機制。
- 同步,就是請求一個‘呼叫’時,在沒有得到結果之前,該呼叫不返回,但是該呼叫一旦返回,就可以得到呼叫結果。即‘呼叫者’主動等待‘呼叫’結果。
- 非同步,是在發出一個‘呼叫’後,這個呼叫就直接返回了,沒有返回結果。即一個非同步過程呼叫發出後,呼叫者不會立刻得到結果,而是在‘呼叫’發出後’,由‘被呼叫者’通過狀態,通知來通知呼叫者,或者通過回撥函式來處理這個呼叫。
舉一個例子,我打電話給書店老闆問他有沒有 《c++ primer》這本書,我需要購買一本,老闆可能會說(同步方式),不好意思麻煩你等稍等一會,我查一下,等他查好了(可能是幾分鐘,也可能幾個小時)告訴你結果(返回結果)。而老闆也有可能會說(非同步方式),不好意思,我需要查一下,查完了我打會電話通知你,然後老闆掛掉了電話(不返回結果)。等老闆查好後,他會給你打電話通知你結果。
阻塞和非阻塞
阻塞和非阻塞關注的是程序在等待呼叫結果時的狀態。
- 阻塞,是指在呼叫結果返回之前,當前程序被掛起,呼叫程序只有在得到結果後才會返回。
- 非阻塞,是指在不能立即得到呼叫結果時,該呼叫不會阻塞當前程序。
繼續上面的例子,當我打電話詢問書店老闆有沒有 《c++ primer》這本書時,我可能會一直在電話前等待(阻塞),直到獲取書店裡到底有沒有這本書的結果,我才去做其他事情。我也可能會不管老闆有沒有給我回復,就去一邊玩去了,當然我還惦記著買書這件事,時不時檢查一下老闆有沒有給我結果。
需要注意的是這裡阻塞與非阻塞與是否同步,非同步無關,跟老闆以何種方式通知我無關。
總結
在瞭解了五種 IO 模型,同步,非同步,阻塞,非阻塞的概念之後,可以得知,同步和非同步是站在‘被呼叫者’的角度出發的,描述的是被呼叫者的通知方式,是等待我完成一件事後才返回給發起呼叫者結果(同步),還是先告訴發起呼叫者我完成後會用哪種方式通知你(非同步)。而阻塞是在發起呼叫者的角度出發的,描述的是發起呼叫者在等待結果時的狀態。是一直等待被呼叫事件的完成,還是在等待期間可以去做其它事情。以上就是我在學習這些知識的過程中的理解,如果有誤,還請大家指出。
相關推薦
Windows I/O模型、同步/非同步、阻塞/非阻塞
同步 所謂同步,就是在發出一個功能呼叫時,在沒有得到結果之前,該呼叫就不返回。按照這個定義,其實絕大多數函式都是同步呼叫(例如sin, isdigit等)。但是一般而言,我們在說同步、非同步的時候,特指那些需要其他部件協作或者需要一定時間完成的任務。最常見的例子就是 SendMessag
linux下的 I/O 模型,同步/非同步,阻塞/非阻塞介紹
同步/非同步,阻塞/非阻塞 一提到網路程式設計中的 I/O 模型,總會涉及到這幾個概念,但是這幾個名詞又容易混淆,於是我想總結一下。 我們先看一下在《UNIX網路程式設計:卷一》中講到的5中 UNIX 下的 I/O 模型,分別是 阻塞式 I/O 非阻塞式
I/O模型:同步I/O和非同步I/O,阻塞I/O和非阻塞I/O
同步(synchronous) IO和非同步(asynchronous) IO,阻塞(blocking) IO和非阻塞(non-blocking)IO分別是什麼,到底有什麼區別? 這個問題其實不同的人給出的答案都可能不同,在大部分的博文中(包括WIKI在內),我們很可能
Linux通用I/O模型
學習Linux系統程式設計,檔案I/O是一個不錯的切入點。首先,日常操作中或多或少都使用過檔案,有一定的概念;其次,檔案I/O可以由幾個最最基礎的系統呼叫完成,降低入門理解難度。 基礎系統呼叫 Linux下I/O操作是通用化的,不僅僅可以用來操作檔案輸入輸出,還可以用來操作管道、FIFO、s
linux下I/O複用與epoll實際使用(二)
上一節《linux下I/O複用與epoll實際使用(一)》主要講解了epoll的原理,這一節結合socket的程式設計,詳解select與epoll程式設計示例。 一、socket程式設計 在TCP/IP協議中“IP地址+TCP或者UDP埠號”唯一標識網路通訊中
Linux 下I/O多路複用總結
select,poll,epoll都是IO多路複用的機制。I/O多路複用就通過一種機制,可以監視多個描述符,一旦某個描述符就緒(一般是讀就緒或者寫就緒),能夠通知程式進行相應的讀寫操作。但select,poll,epoll本質上都是同步I/O,因為他們都需要在讀寫事件
Linux 網路 I/O 模型簡介(圖文)
1、介紹 Linux 的核心將所有外部裝置都看做一個檔案來操作(一切皆檔案),對一個檔案的讀寫操作會呼叫核心提供的系統命令,返回一個file descriptor(fd,檔案描述符)。而對一個socket的讀寫也會有響應的描述符,稱為socket fd(soc
Linux系統I/O模型詳解
使用 通過 數據加載 導致 字節 gin 某個文件 lec locked 前言 本文從基本的原理上了解用戶空間、內核空間、進程上下文、及系統的五種常用I/O模型,加深對Linux系統的理解。 1. 概念說明 1.1 用戶空間與內核空間 現在操作系統都是采用虛擬存儲器,那麽對
併發並行,同步非同步,同步鎖,遞迴鎖,同步條件(event),訊號量(Semaphore),佇列(queue),生產者消費者
併發&並行 併發:是指系統具有處理 多個任務(動作)的能力(分著切換進行)。一個cpu就能實現併發,一邊聽歌一邊打遊戲 並行:是指系統具有同時處理 多個任務(唯一的時刻,同一時刻)。多核(4核處理4個任務) 並行是併發的子集 同步&非同步 同步:
MPI,同步/非同步,阻塞/非阻塞通訊,集合通訊,Gather/Scatter
1. MPI MPI(Message Passing Interface)是一種訊息傳遞介面,是一個訊息傳遞漢書庫的標準說明。在基於MPI程式設計模型中,計算是由一個或多個彼此通過呼叫庫函式進行訊息收、發通訊的程序所組成。MPI為程式設計師提供一個並行環境庫,程式設計師通過
socket阻塞與非阻塞,同步與非同步、I/O模型(轉載只為查閱方便,若有侵權,立刪)
socket阻塞與非阻塞,同步與非同步 作者:huangguisu 1. 概念理解 在進行網路程式設計時,我們常常見到同步(Sync)/非同步(Async),阻塞(Block)/非阻塞(Unbl
socket阻塞與非阻塞,同步與非同步、I/O模型
1. 概念理解 在進行網路程式設計時,我們常常見到同步(Sync)/非同步(Async),阻塞(Block)/非阻塞(Unblock)四種呼叫方式: 同步/非同步主要針對C端: 同步:所謂同步,就是在c端發出一個功能呼叫時,在沒有得到結果之前,該
I/O 模型,阻塞非阻塞,同步非同步
一個IO操作,需要2步。 以read為例, read --> sys_Read --> 驅動中的buffer資料 OR 網路中的udp/tcp報文 等等 同步/非同步 是否阻塞在第二步。 也就是 sys_Read -->
Linux下五種I/O模型詳解(阻塞IO、非阻塞IO、IO複用、訊號驅動、非同步IO)
文章轉載自微信公眾號:漫話程式設計 1 什麼是I/O 程式是由資料+指令構成的,執行程式的過程可以分成下面這幾步: 1.將程式碼載入到記憶體中,逐條執行記憶體中的程式碼 2.在執行程式碼的過程中,可能需要對檔案的讀寫,即將檔案輸入(Input)
socket阻塞與非阻塞 同步與非同步 I/O模型
分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow 也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!  
linux 下的五種I/O模型
Linux下的五種I/O通訊模型 同步,非同步,阻塞,非阻塞的概念 首先,需要明確的一個問題就是,通常程式是執行在使用者態下,如果需要進行I/O操作,那麼就會發出系統呼叫(System call),由使用者態轉變為核心態,由作業系統去完成I/O操作,實際上應用程
聊聊阻塞與非阻塞、同步與非同步、I/O模型
1. 概念理解 在進行網路程式設計時,我們常常見到同步(Sync)/非同步(Async),阻塞(Block)/非阻塞(Unblock)四種呼叫方式: 同步/非同步主要針對C端: 同步: 所謂同步,就是在c端發出一個功能呼叫時,在沒有得到結果之前,該呼叫就不返回。也就是必須一件一件事做,等前一件做完了才能做
Linux下的5種I/O模型(轉)
Linux下的五種I/O模型: l 阻塞I/O l &nbs
網路程式設計中阻塞與非阻塞、同步與非同步、I/O模型的理解
1. 概念理解 在進行網路程式設計時,我們常常見到同步(Sync)/非同步(Async),阻塞(Block)/非阻塞(Unblock)四種呼叫方式:同步:所謂同步,就是在發出一個功能呼叫時,在沒有得到結果之前,該呼叫就不返回。也就是必須一件一件事做,等前一件做完了才能做下一件事。 例如
簡明網路I/O模型---同步非同步阻塞非阻塞之惑
網路I/O模型 人多了,就會有問題。web剛出現的時候,光顧的人很少。近年來網路應用規模逐漸擴大,應用的架構也需要隨之改變。C10k的問題,讓工程師們需要思考服務的效能與應用的併發能力。 網路應用需要處理的無非就是兩大類問題,網路I/O,資料計算。相對於後者,網路I/O的延