Socket--I/O模型

I/O模型

通常來說,IO操作包括:對硬盤的讀寫,對socket的讀寫以及外設的讀寫。
一個完整的IO請求操作包括以下兩部分:

  • 查看數據是否就緒;
  • 進行數據拷貝(內核將數據拷貝到用戶線程)。

在《Unix網絡編程》中提到了五中IO模型,分別是:阻塞IO、非阻塞IO、多路複用IO、信號驅動IO、和異步IO。

阻塞IO模型:

最傳統的一種IO模型,即在讀寫操作過程中發生阻塞現象。

當用戶線程發出IO請求之後,內核會查看數據是否就緒,如果沒有就緒就會等待數據就緒,而用戶線程就會處於阻塞狀態,用戶將交出CPU的佔用。當數據就緒之後,內核會將數據拷貝到用戶線程,並返回結果個給用戶線程,用戶線程才接觸block狀態。

應該注意到,在阻塞過程中,其他應用進程還可以執行,因此阻塞並不意味着整個操作系統都被阻塞。因爲其他應用程序還可以執行,所以該線程不消耗CPU,這種模型CPU的利用率會比較高。

在這裏插入圖片描述
典型的阻塞IO的例子爲:

data = socket.read();  #如果沒有就緒,就會一直阻塞在read方法

非阻塞IO模型:

當用戶線程發起一個read操作後,並不需要等待,而是馬上得到了一個結果。如果結果是error時,它就知道數據還沒有準備好,於是他可以再次發送read操作,一旦內核中的數據準備好了,並且又再次收到了用戶線程的請求,那麼它馬上就將數據拷貝到了用戶線程,然後返回。(不斷的執行read操作,來獲知IO是否完成,這種方法叫做輪詢(polling))。

在這裏插入圖片描述

由於CPU要處理更多的系統調用,因此這種模型的CPU的利用率低。
典型的IO阻塞模型爲:

while(true){
	data = socket.read();
	if(data!=error){
		處理數據;
		break;
	}
}

多路複用IO模型

  • 多路複用IO模型是目前使用比較多的模型,在多路複用IO模型中,會有一個線程不斷去輪詢多個socket的狀態,只有當socket正真需要讀寫事件時,才真正調用實際的IO讀寫操作。因爲在多路複用IO模型中,只需要使用一個線程就可以管理多個socket,系統不需要建立新的進程或者線程,也不必要維護這些進程和線程,並且只有真正有socket讀寫時間進行時,纔會使用IO資源,所以大大減少了資源的佔用
  • IO多路複用模式,通過一個線程管理多個socket,只用當socket真正有讀寫事件發生纔會佔用資源來進行實際的讀寫操作。因此IO多路複用更適合連接數比較多的情況。
  • 多路複用IO中輪詢每個socket狀態時內核進行,這個比非阻塞IO通過用戶線程要高的多。

在這裏插入圖片描述

不過要注意的是,多路複用IO模型是通過輪詢的方式來檢測是否有時間到達,並且對到達的時間逐一進行響應。因此對於多路複用IO模型來說,一旦事件響應很大,那麼就會導致後續的事件遲遲不能到達,並且會影響心得時間輪詢。

信號驅動IO模型

在信號驅動IO模型中,當用戶線程發起一個IO請求操作,會給對應的socket註冊一個信號函數,然後用戶線程會繼續執行,當內核數據就緒時會發送一個信號給用戶線程,用戶線程接收到信號之後,便在信號函數中調用IO讀寫操作來進行實際的IO請求操作

在這裏插入圖片描述

異步IO模型

  • 在異步IO模型中,當用戶線程發起read操作之後,立即就可以開始做其它的事。而另一方面,從內核的角度,當它受到一個異步read之後,它會立即返回,說明read請求已經成功發起了,因此不會對用戶線程產生任何的block。然後內核等待數據準備完成,然後將數據拷貝到用戶線程,當之一切都完成之後,內核會給用戶線程發送一個信號,告訴read操作完成了。
  • 異步IO模型中,IO操作的兩個階段都不會阻塞用戶線程,這兩個階段都是由內核自動完成,然後發送一個信號告知用戶線程操作已經完成。

在這裏插入圖片描述

異步IO模型和信號驅動IO模型的不同在於:異步IO模型是通知應用進程IO完成,而信號驅動IO則通知的是應用進程可以開始IO。

五大IO模型的比較:

  • 同步IO:將數據從內核緩衝區複製到應用進程緩衝區的階段,應用進程會阻塞。
  • 異步IO:第二階段應用進程不會阻塞

同步IO:阻塞IO、非阻塞IO、多路複用IO、信號驅動IO

IO複用的三種方法將下一篇介紹

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章