您好,登錄后才能下訂單哦!
本篇內容主要講解“Linux的I/O模型概念是什么”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓小編來帶大家學習“Linux的I/O模型概念是什么”吧!
1. 阻塞I/O模型
老李去火車站買票,排隊三天買到一張退票。
耗費:在車站吃喝拉撒睡 3天,其他事一件沒干。
2. 非阻塞I/O模型
老李去火車站買票,隔12小時去火車站問有沒有退票,三天后買到一張票。
耗費:往返車站6次,路上6小時,其他時間做了好多事。
3. I/O復用模型
1.select/poll
老李去火車站買票,委托黃牛,然后每隔6小時電話黃牛詢問,黃牛三天內買到票,然后老李去火車站交錢領票。
耗費:往返車站2次,路上2小時,黃牛手續費100元,打電話17次
2.epoll
老李去火車站買票,委托黃牛,黃牛買到后即通知老李去領,然后老李去火車站交錢領票。
耗費:往返車站2次,路上2小時,黃牛手續費100元,無需打電話
4. 信號驅動I/O模型
老李去火車站買票,給售票員留下電話,有票后,售票員電話通知老李,然后老李去火車站交錢領票。
耗費:往返車站2次,路上2小時,免黃牛費100元,無需打電話
5. 異步I/O模型
老李去火車站買票,給售票員留下電話,有票后,售票員電話通知老李并快遞送票上門。
耗費:往返車站1次,路上1小時,免黃牛費100元,無需打電話
總結:
1同2的區別是:自己輪詢
2同3的區別是:委托黃牛
3同4的區別是:電話代替黃牛
4同5的區別是:電話通知是自取還是送票上門
2、講解
nginx使用epoll接收請求的過程是怎樣的, 多看看上面個圖就了解了。提醒下,ngnix會有很多鏈接進來, epoll會把他們都監視起來,然后像撥開關一樣,誰有數據就撥向誰,然后調用相應的代碼處理。
橫軸Dead connections 就是鏈接數的意思,叫這個名字只是它的測試工具叫deadcon. 縱軸是每秒處理請求的數量,你可以看到,epoll每秒處理請求的數量基本不會隨著鏈接變多而下降的。poll 和/dev/poll 就很慘了。可是epoll 有個致命的缺點。。只有linux支持
在知乎上面看到一些解釋如下:
截圖如下:
3、總結
阻塞、非阻塞、多路IO復用,都是同步IO,異步必定是非阻塞的,所以不存在異步阻塞和異步非阻塞的說法。真正的異步IO需要CPU的深度參與。換句話說,只有用戶線程在操作IO的時候根本不去考慮IO的執行全部都交給CPU去完成,而自己只等待一個完成信號的時候,才是真正的異步IO。所以,拉一個子線程去輪詢、去死循環,或者使用select、poll、epool,都不是異步。
文件的讀寫方式各有千秋,對于文件的 I/O 分類也非常多,常見的有
緩沖與非緩沖 I/O
直接與非直接 I/O
阻塞與非阻塞 I/O VS 同步與異步 I/O
接下來,分別對這些分類討論討論。
緩沖與非緩沖 I/O
文件操作的標準庫是可以實現數據的緩存,那么根據「是否利用標準庫緩沖」,可以把文件 I/O 分為緩沖 I/O 和非緩沖 I/O:
緩沖 I/O,利用的是標準庫的緩存實現文件的加速訪問,而標準庫再通過系統調用訪問文件。
非緩沖 I/O,直接通過系統調用訪問文件,不經過標準庫緩存。
這里所說的「緩沖」特指標準庫內部實現的緩沖。
比方說,很多程序遇到換行時才真正輸出,而換行前的內容,其實就是被標準庫暫時緩存了起來,這樣做的目的是,減少系統調用的次數,畢竟系統調用是有 CPU 上下文切換的開銷的。
直接與非直接 I/O
我們都知道磁盤 I/O 是非常慢的,所以 Linux 內核為了減少磁盤 I/O 次數,在系統調用后,會把用戶數據拷貝到內核中緩存起來,這個內核緩存空間也就是「頁緩存」,只有當緩存滿足某些條件的時候,才發起磁盤 I/O 的請求。
那么,根據是「否利用操作系統的緩存」,可以把文件 I/O 分為直接 I/O 與非直接 I/O:
直接 I/O,不會發生內核緩存和用戶程序之間數據復制,而是直接經過文件系統訪問磁盤。
非直接 I/O,讀操作時,數據從內核緩存中拷貝給用戶程序,寫操作時,數據從用戶程序拷貝給內核緩存,再由內核決定什么時候寫入數據到磁盤。
如果你在使用文件操作類的系統調用函數時,指定了 O_DIRECT
標志,則表示使用直接 I/O。如果沒有設置過,默認使用的是非直接 I/O。
如果用了非直接 I/O 進行寫數據操作,內核什么情況下才會把緩存數據寫入到磁盤?
以下幾種場景會觸發內核緩存的數據寫入磁盤:
在調用 write
的最后,當發現內核緩存的數據太多的時候,內核會把數據寫到磁盤上;
用戶主動調用 sync
,內核緩存會刷到磁盤上;
當內存十分緊張,無法再分配頁面時,也會把內核緩存的數據刷到磁盤上;
內核緩存的數據的緩存時間超過某個時間時,也會把數據刷到磁盤上;
阻塞與非阻塞 I/O VS 同步與異步 I/O
為什么把阻塞 / 非阻塞與同步與異步放一起說的呢?因為它們確實非常相似,也非常容易混淆,不過它們之間的關系還是有點微妙的。
先來看看阻塞 I/O,當用戶程序執行 read
,線程會被阻塞,一直等到內核數據準備好,并把數據從內核緩沖區拷貝到應用程序的緩沖區中,當拷貝過程完成,read
才會返回。
注意,阻塞等待的是「內核數據準備好」和「數據從內核態拷貝到用戶態」這兩個過程。過程如下圖:
非阻塞 I/O
注意,這里最后一次 read 調用,獲取數據的過程,是一個同步的過程,是需要等待的過程。這里的同步指的是內核態的數據拷貝到用戶程序的緩存區這個過程。
舉個例子,訪問管道或 socket 時,如果設置了 O_NONBLOCK
標志,那么就表示使用的是非阻塞 I/O 的方式訪問,而不做任何設置的話,默認是阻塞 I/O。
應用程序每次輪詢內核的 I/O 是否準備好,感覺有點傻乎乎,因為輪詢的過程中,應用程序啥也做不了,只是在循環。
為了解決這種傻乎乎輪詢方式,于是 I/O 多路復用技術就出來了,如 select、poll,它是通過 I/O 事件分發,當內核數據準備好時,再以事件通知應用程序進行操作。
這個做法大大改善了應用進程對 CPU 的利用率,在沒有被通知的情況下,應用進程可以使用 CPU 做其他的事情。
下圖是使用 select I/O 多路復用過程。注意,read
獲取數據的過程(數據從內核態拷貝到用戶態的過程),也是一個同步的過程,需要等待:
異步 I/O
下面這張圖,總結了以上幾種 I/O 模型:
在前面我們知道了,I/O 是分為兩個過程的:
數據準備的過程
數據從內核空間拷貝到用戶進程緩沖區的過程
阻塞 I/O 會阻塞在「過程 1 」和「過程 2」,而非阻塞 I/O 和基于非阻塞 I/O 的多路復用只會阻塞在「過程 2」,所以這三個都可以認為是同步 I/O。
異步 I/O 則不同,「過程 1 」和「過程 2 」都不會阻塞。
用故事去理解這幾種 I/O 模型
舉個你去飯堂吃飯的例子,你好比用戶程序,飯堂好比操作系統。
阻塞 I/O 好比,你去飯堂吃飯,但是飯堂的菜還沒做好,然后你就一直在那里等啊等,等了好長一段時間終于等到飯堂阿姨把菜端了出來(數據準備的過程),但是你還得繼續等阿姨把菜(內核空間)打到你的飯盒里(用戶空間),經歷完這兩個過程,你才可以離開。
非阻塞 I/O 好比,你去了飯堂,問阿姨菜做好了沒有,阿姨告訴你沒,你就離開了,過幾十分鐘,你又來飯堂問阿姨,阿姨說做好了,于是阿姨幫你把菜打到你的飯盒里,這個過程你是得等待的。
基于非阻塞的 I/O 多路復用好比,你去飯堂吃飯,發現有一排窗口,飯堂阿姨告訴你這些窗口都還沒做好菜,等做好了再通知你,于是等啊等(select
調用中),過了一會阿姨通知你菜做好了,但是不知道哪個窗口的菜做好了,你自己看吧。于是你只能一個一個窗口去確認,后面發現 5 號窗口菜做好了,于是你讓 5 號窗口的阿姨幫你打菜到飯盒里,這個打菜的過程你是要等待的,雖然時間不長。打完菜后,你自然就可以離開了。
異步 I/O 好比,你讓飯堂阿姨將菜做好并把菜打到飯盒里后,把飯盒送到你面前,整個過程你都不需要任何等待。
到此,相信大家對“Linux的I/O模型概念是什么”有了更深的了解,不妨來實際操作一番吧!這里是億速云網站,更多相關內容可以進入相關頻道進行查詢,關注我們,繼續學習!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。