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