1. 程式人生 > >linux 下的五種I/O模型

linux 下的五種I/O模型

Linux下的五種I/O通訊模型

同步,非同步,阻塞,非阻塞的概念

首先,需要明確的一個問題就是,通常程式是執行在使用者態下,如果需要進行I/O操作,那麼就會發出系統呼叫(System call),由使用者態轉變為核心態,由作業系統去完成I/O操作,實際上應用程式本身沒有權利操作I/O。

同步和非同步:都是針對應用程式和作業系統之間互動而言的。同步的話,如果上層應用程式不主動詢問作業系統的話,作業系統不會主動通知應用程式。非同步的話,作業系統主動通知應用程式。 阻塞:如果條件不滿足的話,作業系統將應用執行緒掛起或者休眠,此時應用執行緒處於阻塞狀態,只有當資料準備好之後或者資料已經從核心空間拷貝到使用者空間,作業系統通知執行緒,此為喚醒執行緒。 非阻塞:如果條件不滿足的話,該方法不會阻塞當前執行緒,而是立即返回一個標誌資訊(資料還沒有準備好),或者timeout之後返回,此時應用執行緒還可以進行其他的操作。

要注意的問題:同步不等同於阻塞,同步呼叫的時候,即便呼叫不返回,但是應用執行緒還處於執行態,還可以做一些其它的事情。而阻塞呼叫時,應用執行緒處於阻塞的狀態。

阻塞I/O模型

應用程式呼叫I/O函式,應用執行緒會阻塞,直到資料準備好為止。如果資料沒有準備好,則應用執行緒一直等待。 在這裡插入圖片描述

非阻塞I/O模型

非阻塞I/O通過應用執行緒反覆呼叫I/O函式(多次呼叫,立即返回);在資料拷貝階段,執行緒還是阻塞的。 我們把socket套接字介面設定為非阻塞的時候,就是告訴作業系統,在沒有資料的時候,不要把我掛起或者休眠,而是返回一個錯誤訊號。 在這裡插入圖片描述

多路複用I/O模型

多路複用I/O模型是目前使用比較多的模型。Java nio實際上就是這種模型。所謂的多路複用,可以理解為在一個應用執行緒裡可以處理多個socket連線,或者同一個埠接受來自多個客戶端的請求(連線,讀,寫)

在這裡插入圖片描述 當然在java nio中對多路複用支援阻塞和非阻塞兩種模式。

多路複用IO與傳統的非阻塞IO的區別在於,在傳統的非阻塞IO中,由使用者執行緒去輪詢socket的狀態,而在多路複用IO中,由核心去輪詢向select註冊的socket的狀態。所以多路複用IO需要作業系統的支援。

訊號驅動I/O

在訊號驅動IO模型中,當用戶執行緒發起一個IO請求操作的時候,會給對應的socket註冊一個訊號函式,然後使用者執行緒繼續執行,當核心資料準備就緒時,會給使用者執行緒傳送一個訊號。使用者執行緒接收到訊號之後,便在訊號函式中呼叫IO讀寫操作進行實際的IO請求操作。

在這裡插入圖片描述

非同步I/O模型

非同步IO模型才是最理想的IO模型,在非同步IO模型中,當用戶執行緒發起read操作之後,立刻就可以開始去做其它的事。而另一方面,從核心的角度,當它受到一個asynchronous read之後,它會立刻返回,說明read請求已經成功發起了,因此不會對使用者執行緒產生任何block。然後,核心會等待資料準備完成,然後將資料拷貝到使用者執行緒,當這一切都完成之後,核心會給使用者執行緒傳送一個訊號,告訴它read操作完成了。也就說使用者執行緒完全不需要實際的整個IO操作是如何進行的,只需要先發起一個請求,當接收核心返回的成功訊號時表示IO操作已經完成,可以直接去使!](

https://img-blog.csdn.net/20181001103522406?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dkX185MDA5MDI=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70)用資料了。 非同步IO模型中,由作業系統核心去等待資料就緒,copy資料到使用者空間,使用者執行緒始終沒有阻塞。

注:linux中並不存在真正的非同步IO,而是通過多路複用的方式去模擬非同步IO。