日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

(四)五种IO模型

發布時間:2024/9/5 编程问答 47 豆豆
生活随笔 收集整理的這篇文章主要介紹了 (四)五种IO模型 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

基本概念

我們之前編寫的套接字程序都是阻塞式的,其實這也是默認的形式?,F在我們需要明確一些概念:

用戶空間和內核空間

?

首先要明確,用戶啟動的應用程序在系統中以一個進程的形式存在,而無論對于網絡數據還是磁盤數據通常來講這個進程都無法直接訪問,必須由內核把數據復制到用戶空間也就是進程所在的內存空間里這個進程才可以訪問。上圖結合了網絡請求和磁盤數據,用戶發起一個HTTP請求,請求一個HTML頁面,這個頁面就在磁盤上,其實就是把這個HTML頁面發送給用戶,用戶的瀏覽器解析HTML語言就顯示了頁面。用戶請求一個頁面其實就是阻塞的,瀏覽器必須等待所有數據返回后才能正確顯示這個頁面。所以這個請求的整個過程是阻塞的也是同步的,因為你無法讓當前這個瀏覽器標簽在等待服務器返回數據的時候去干別的。

其實對于我們之前寫的程序也是一樣,雖然服務器做的事情就是回顯客戶端發送的數據,其實客戶端發送過來也是先進入服務器內核的TCP協議棧,而你的服務端程序運行在用戶空間,內核需要把這個數據從內核空間復制到用戶空間,然后服務器端程序才能拿到進而進行處理然后在進行發送,發送的過程其實就是接受的反向過程。

名詞解釋

阻塞:進程發起IO調用時,如果這個IO沒有準備好數據那么進程調用的這個函數將不會返回,那么這個進程就要進入睡眠狀態,也就是當前進程會被掛起。當數據拷貝到用戶空間后才返回。

非阻塞:進程發起IO調用時,被調用函數在完成IO之前不會阻塞當前進程,而是立即返回,返回的含義你可以理解為數據還沒準備好。雖然進程不阻塞,但是它需要頻繁的調用之前的函數看看數據有沒有準備好,所以這就是忙等,也叫輪訓。

同步:進程發起一個過程調用(功能、函數)調用后,在沒得到結果之前,該調用將不會返回。相當于你買麥當勞,你拿著小票在取餐處等著,如果你的餐沒有做好那么服務員是不會給你端上來的。

異步:進程發起一個過程調用,即使不能立即得到結果,但也會得到返回值。當IO完成后,內核會通知進程資源已經準備好了,你可以來讀取了。你可以理解為飯店點菜,點好了你可以干別的,菜好了服務員就給你端上來。

同步和阻塞、異步和非阻塞看起來概念上很像,但是他們所描述的對象不同,同步或異步是被調用者如何響應調用者,而阻塞或非阻塞是調用者如何被處理的?;蛘邠Q句話說阻塞或非阻塞這種狀態的描述對象是進程也就調用者被如何處理的,而同步或異步的這種處理方式所描述的對象是被調用者會如何響應調用者的。所以說的是同一個事情,但是描述的時候所站在的角度不同。

如果要把同步、異步、阻塞和非阻塞對應到后面要說的IO模型上的話,那么阻塞和非阻塞就是進程調用的系統函數是否立即返回無論數據準備好沒有;同步和異步就是數據準備好后從內核空間拷貝到用戶空間的過程中進程是否阻塞。

五種調用模型

阻塞式IO

?

阻塞式IO也是我們之前一直使用的模式其實也是默認模式。一次系統調用分為2個階段:

  • 數據從磁盤到內核空間的緩沖區
  • 內核把內核空間的數據復制到進程空間,然后刪除內核空間數據
  • 進程調用recvfrom就被阻塞,這時候就等數據,數據準備好了就從內核空間復制到用戶空間,復制完成之后recvfrom函數才返回,這時候進程才開始對數據進行處理。在上面的圖示數據準備好我們理解為數據可讀,結合之前的例子就是我們的服務端程序阻塞在accept處,當有新連接進來之后連接套接字變為可讀這時候就accept就返回了,看下圖代碼:

    另外在接收客戶端數據的時候服務端調用recv函數其實也是阻塞在這里,因為它要等著客戶端發數據來,如下圖:

    因為connFd代表一個與客戶端的連接套接字,這個套接字可讀證明有數據到達且被復制到進程的緩沖區(也就是用戶空間),這時候這個函數才返回,否則就一直阻塞。

    非阻塞式IO

    你明白了上面的阻塞式IO后再看這個非阻塞式的就很好理解,調用函數不阻塞立即返回,但是內核不會告訴你啥時候數據到達,你的反復調用,如果第N次調用剛好數據準備好,那么就阻塞了,這時候開始等待數據復制,復制完畢函數返回。這種方式會大量消耗CPU時間。

    IO復用

    在這種模型中,這時候并不是進程直接發起資源請求的系統調用去請求資源,進程不會被“全程阻塞”,進程是調用select或poll函數。進程不是被阻塞在真正IO上了,而是阻塞在select或者poll上了。Select或者poll幫助用戶進程去輪詢那些IO操作是否完成。

    不過你可以看到之前都只使用一個系統調用,在IO復用中反而是用了兩個系統調用,但是使用IO復用你就可以等待多個描述符也就是通過單進程單線程實現并發處理,同時還可以兼顧處理套接字描述符和其他描述符。

    信號驅動模型

    讓內核在文件描述符就緒時通過信號通知進程。從上圖可以看出這種模型進程建立信號處理程序然后立即返回,當數據準備好后發送信號通知進程,然后進程調用recvfrom系統調用進行復制數據,當數據復制到用戶空間后函數返回(信號驅動機制需要內核支持)。這就相當于是你點菜下單后可以繼續干其他的事情雖然菜好了會通知你,但是你需要自己去拿。但這里有個情況,如果通知進程來拿數據,但是進程沒來怎么辦?這就引出了水平觸發和邊緣觸發概念

    邊緣觸發(Edge triggered):以epoll為例,當被監控的文件描述符上有可讀寫事件時,被調用者(epoll_wait())通知進程去讀寫,如果一次沒有把全部數據讀寫完畢比如讀寫緩沖區太小,那么下次調用epoll_wait()時被調用者它不會通知進程,它只通知一次,直到該文件描述符上出現第二次可讀寫事件才會通知。信號驅動IO是邊緣觸發模型,epoll()支持水平也支持邊緣,默認是水平觸發。

    水平觸發(Level triggered):以epoll為例,當被監控的文件描述符上有可讀寫事件時,被調用者(epoll_wait())通知進程去讀寫,如果一次沒有把全部數據讀寫完畢比如讀寫緩沖區太小,那么下次調用epoll_wait()時,它還會通知進程在上次沒有讀寫完的文件描述符上繼續讀寫,當然如果你一直不讀寫,它會一直通知。如果系統中有大量你需要讀寫的文件描述符,而且它每次都返回,這會大大降低程序檢查自己關心的文件描述符的效率,相比之下邊緣觸發效率更高。Select()和poll()都是水平觸發的。

    異步IO模型

    這種模型可以看出全程無阻塞,就等于你點菜下單后你可以續干其他的事情,菜做好了服務員會給你端上來,剩下的就是你如何處理這些菜。從效率上來講異步IO模型是最高的。

    5種IO模型比較

    從上圖可以效率從左至右逐步提高,其實IO復用也不是不阻塞,只是阻塞在像select這種IO復用函數這里。

    轉載于:https://www.cnblogs.com/rexcheny/p/9721246.html

    總結

    以上是生活随笔為你收集整理的(四)五种IO模型的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。