日本综合一区二区|亚洲中文天堂综合|日韩欧美自拍一区|男女精品天堂一区|欧美自拍第6页亚洲成人精品一区|亚洲黄色天堂一区二区成人|超碰91偷拍第一页|日韩av夜夜嗨中文字幕|久久蜜综合视频官网|精美人妻一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時(shí)間:8:30-17:00
你可能遇到了下面的問(wèn)題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營(yíng)銷(xiāo)解決方案
Linux下的高效異步IO:libaio詳解(linuxlibaio)

隨著計(jì)算機(jī)的發(fā)展,IO操作成為了CPU瓶頸之一。為了提高IO性能,操作系統(tǒng)提供了異步IO接口。而Linux下的異步IO接口庫(kù)——libo,又是如何進(jìn)行高效異步IO的呢?下面為大家詳細(xì)介紹。

網(wǎng)站建設(shè)哪家好,找創(chuàng)新互聯(lián)!專(zhuān)注于網(wǎng)頁(yè)設(shè)計(jì)、網(wǎng)站建設(shè)、微信開(kāi)發(fā)、重慶小程序開(kāi)發(fā)、集團(tuán)企業(yè)網(wǎng)站建設(shè)等服務(wù)項(xiàng)目。為回饋新老客戶創(chuàng)新互聯(lián)還提供了殷都免費(fèi)建站歡迎大家使用!

一、異步IO介紹

異步IO分為阻塞IO和非阻塞IO兩種模式。阻塞IO模式下,當(dāng)程序執(zhí)行IO操作時(shí)會(huì)一直阻塞等待IO操作完成后才會(huì)繼續(xù)執(zhí)行后續(xù)代碼。而在非阻塞IO模式下,程序在發(fā)起IO操作之后不會(huì)阻塞,而是可以繼續(xù)執(zhí)行后續(xù)代碼。

但是,非阻塞IO也有一個(gè)問(wèn)題,就是需要開(kāi)發(fā)者不斷地輪詢IO是否完成,這樣會(huì)使CPU資源被浪費(fèi)。于是就有了異步IO,也叫多路復(fù)用IO。

異步IO模式下,程序會(huì)向操作系統(tǒng)發(fā)起IO請(qǐng)求,并設(shè)置一個(gè)回調(diào)函數(shù),當(dāng)IO操作完成后會(huì)回調(diào)這個(gè)函數(shù)。這樣的方式既不會(huì)阻塞程序,也不會(huì)浪費(fèi)CPU資源,同時(shí)還可以讓程序及時(shí)處理IO結(jié)果。

二、Linux異步IO庫(kù)簡(jiǎn)介

Linux異步IO庫(kù)有三種,分別是POSIX異步IO、O和libo。其中,POSIX異步IO是一種非常簡(jiǎn)單的異步IO方式,只能對(duì)單一文件進(jìn)行操作,操作方式非常單一。O是Linux下的異步IO標(biāo)準(zhǔn)庫(kù),通過(guò)外部調(diào)用使用,實(shí)現(xiàn)可移植性與統(tǒng)一性。而libo是Linux特有的異步IO庫(kù),封裝了O和POSIX異步IO,相比其他兩種更加高效。

三、libo的工作原理

libo的工作原理分為如下步驟:

1.創(chuàng)建一個(gè)IO上下文 OCtx: OCtx是libo中的一個(gè)結(jié)構(gòu)體,內(nèi)部保存了一個(gè) Linux kernel 需要的O環(huán)境。

2.創(chuàng)建事件結(jié)構(gòu)體event:event即為IO操作的最小單位,包含操作類(lèi)型(讀/寫(xiě))、文件描述符、IO緩存區(qū)、數(shù)據(jù)長(zhǎng)度等。

3.提交事件:將需要進(jìn)行異步IO操作的event加入到OCtx中,并提交給Linux kernel。在這一步之后,程序就可以繼續(xù)執(zhí)行了。

4.等待IO完成事件:程序可以通過(guò)io_getevents函數(shù)輪詢Linux kernel,查詢IO事件是否已經(jīng)完成。當(dāng)有IO事件完成時(shí),會(huì)調(diào)用設(shè)置的回調(diào)函數(shù)。在回調(diào)函數(shù)中,處理IO結(jié)果,判斷是否每一條IO操作已經(jīng)結(jié)束。如果所有操作都結(jié)束了,則關(guān)閉IO上下文OCtx。

通過(guò)以上步驟,就可以實(shí)現(xiàn)高效異步IO操作啦。

四、libo API介紹

libo提供了詳細(xì)的API,讓程序開(kāi)發(fā)者可以通過(guò)這些API快速地進(jìn)行高效IO操作。以下是libo的五個(gè)核心API介紹:

io_setup:創(chuàng)建一個(gè)異步IO上下文。

io_submit:提交IO請(qǐng)求。

io_getevents:查詢io操作結(jié)果。io函數(shù)的所有結(jié)果都會(huì)保存在events中。

io_destroy:銷(xiāo)毀一個(gè)異步IO上下文。

io_cancel:用于取消任何還沒(méi)有完成的IO操作。

除了上述API外,libo還提供了其他一系列的輔助函數(shù),例如分配內(nèi)存等。開(kāi)發(fā)者可以在官方文檔中查看詳細(xì)說(shuō)明。

五、實(shí)際使用

在實(shí)際開(kāi)發(fā)中,libo也是被廣泛使用的。比如,通過(guò)libo可以在程序執(zhí)行中異步讀取磁盤(pán)數(shù)據(jù),加快程序處理速度。同時(shí),libo還可以做到高效網(wǎng)絡(luò)IO處理。

在使用libo時(shí),需要注意一下幾點(diǎn):

1.開(kāi)辟足夠的線程,來(lái)接收獲取IO操作的結(jié)果。

2.在使用前,需要特別注意一下文件描述符的打開(kāi)方式。

3.需要特別注意線程與線程之間的同步與互鎖。

除了以上注意事項(xiàng)外,其實(shí)使用libo還是相當(dāng)簡(jiǎn)單的。

六、

libo作為L(zhǎng)inux操作系統(tǒng)下的異步IO庫(kù),能夠?yàn)槌绦蛱峁└咝У腎O操作方式。通過(guò)對(duì)libo提供的API的靈活使用,程序開(kāi)發(fā)者能夠非常便捷地實(shí)現(xiàn)高效異步IO操作。在實(shí)際開(kāi)發(fā)過(guò)程中,合理使用libo能夠?yàn)槌绦虻姆€(wěn)定性和性能提供很大幫助。

成都網(wǎng)站建設(shè)公司-創(chuàng)新互聯(lián)為您提供網(wǎng)站建設(shè)、網(wǎng)站制作、網(wǎng)頁(yè)設(shè)計(jì)及定制高端網(wǎng)站建設(shè)服務(wù)!

面試 linux 文件系統(tǒng)怎樣io到底層

前言:本文主要講解LinuxIO調(diào)度層的三種模式:cfp、deadline和noop,并給出各自的優(yōu)化和適用場(chǎng)景建議。IO調(diào)度發(fā)生在Linux內(nèi)核的IO調(diào)度層。這個(gè)層次是針對(duì)Linux的整體IO層次體系來(lái)說(shuō)的。從read()或者write()系統(tǒng)調(diào)用的角度來(lái)說(shuō),Linux整體IO體系可以分為七層,它們分別是:VFS層:虛擬文件系統(tǒng)層。由于內(nèi)核要跟多種文件系統(tǒng)打交道,而每一種文件系統(tǒng)所實(shí)現(xiàn)的數(shù)據(jù)結(jié)構(gòu)和相關(guān)方法都可能不盡相同,所以,內(nèi)核抽象了這一層,專(zhuān)門(mén)用來(lái)適配各種文件系統(tǒng),并對(duì)外提供統(tǒng)一操作接口。文件系統(tǒng)層:不同的文件系統(tǒng)實(shí)現(xiàn)自己的操作過(guò)程,提供自己特有的特征,具體不多說(shuō)了,大家愿意的話自己去看代碼即可。頁(yè)緩存層:負(fù)責(zé)真對(duì)page的緩存。通用塊層:由于絕大多數(shù)情況的io操作是跟塊設(shè)備打交道,所以Linux在此提供了一個(gè)類(lèi)似vfs層的塊設(shè)備操作抽象層。下層對(duì)接各種不同屬性的塊設(shè)備,對(duì)上提供統(tǒng)一的BlockIO請(qǐng)求標(biāo)準(zhǔn)。IO調(diào)度層:因?yàn)榻^大多數(shù)的塊設(shè)備都是類(lèi)似磁盤(pán)這樣的設(shè)判型搜備,所以有必要根據(jù)這類(lèi)設(shè)備的特點(diǎn)以及應(yīng)用的不同特點(diǎn)來(lái)設(shè)置一些不同的調(diào)度算法和隊(duì)列。以便在不同的應(yīng)用環(huán)境下有針對(duì)性的提高磁盤(pán)的讀寫(xiě)效率,這里就是大名鼎鼎的Linux電梯所起作用的地方。針對(duì)機(jī)械硬盤(pán)的各種調(diào)度方法就是在這實(shí)現(xiàn)的。塊設(shè)備驅(qū)動(dòng)層:驅(qū)動(dòng)層對(duì)外提供相對(duì)比較高級(jí)的設(shè)備操作接口,往往是C語(yǔ)言的,而下層對(duì)接設(shè)備本身的操作方法和規(guī)范。塊設(shè)備層:這層就是具體的物理設(shè)備了,定義了各種真對(duì)設(shè)備操作方法和規(guī)范。有一個(gè)已經(jīng)整理好的,非常經(jīng)典,一圖勝千言:我們今天要研究的內(nèi)容主要在IO調(diào)度這一層。它要解決的核心問(wèn)題是,如何提高塊設(shè)備IO的整體性能?這一層也主要是針對(duì)機(jī)械硬盤(pán)結(jié)構(gòu)而設(shè)計(jì)的。眾所周知,機(jī)械硬盤(pán)的存儲(chǔ)介質(zhì)是磁盤(pán),磁頭在盤(pán)片上移動(dòng)進(jìn)行磁道尋址,行為類(lèi)似播放一張唱片。這種結(jié)構(gòu)的特點(diǎn)是,順序訪問(wèn)時(shí)吞吐量較高,但是如果一旦對(duì)盤(pán)片有隨機(jī)訪問(wèn),那么大量的時(shí)間都會(huì)浪費(fèi)在磁頭的移動(dòng)上,這時(shí)候就會(huì)導(dǎo)致每次IO的響應(yīng)時(shí)間變長(zhǎng),極大的降低IO的響應(yīng)速度。磁頭在盤(pán)片上尋道的操作,類(lèi)似電梯調(diào)度,實(shí)際上在最開(kāi)始的時(shí)期,Linux把這個(gè)算法命名為L(zhǎng)inux電梯算法,即:如果在尋道的過(guò)程中,能把順序路過(guò)的相關(guān)磁道的數(shù)據(jù)請(qǐng)求都“順便”處理掉,那么就可以在比較小影響響應(yīng)速度的前提下,提高整體IO的吞吐量。這就是我們?yōu)槭裁匆O(shè)計(jì)IO調(diào)度算法的原因。目前在內(nèi)核中默認(rèn)開(kāi)啟了三種算法/模式:noop,cfq和deadline。嚴(yán)格算應(yīng)該是兩種:因?yàn)橹环N叫做noop,就是空操作調(diào)度算法,也就是沒(méi)有任何調(diào)度操作,并不對(duì)io請(qǐng)求進(jìn)行排序,僅僅做適當(dāng)?shù)膇o合并的一個(gè)fifo隊(duì)列。目前內(nèi)核中默認(rèn)的調(diào)度算法應(yīng)該是cfq,叫做完全公平隊(duì)列調(diào)度。這個(gè)調(diào)度算法人如其名,它試圖給所有進(jìn)程提供一個(gè)完全公平的IO操作環(huán)境。注:請(qǐng)大家一定記住這個(gè)詞語(yǔ),cfq,完全公平隊(duì)列調(diào)度,不然下文就沒(méi)法看了。cfq為每個(gè)進(jìn)程創(chuàng)建一個(gè)同步IO調(diào)度隊(duì)列,并默認(rèn)以時(shí)間片和請(qǐng)求數(shù)限定的方式分配IO資源,以此保證每個(gè)進(jìn)程的IO資源占用是公平的,cfq還實(shí)現(xiàn)了針對(duì)進(jìn)程租檔級(jí)別的優(yōu)先級(jí)調(diào)度,這個(gè)我們后面會(huì)詳細(xì)解釋。查看和修改IO調(diào)度算法的方法是:cfq是通用服務(wù)器比較好的IO調(diào)度算法選擇,對(duì)桌面用戶也是比較好的選擇。但是對(duì)于很多IO壓力較大的場(chǎng)景就并不是很適應(yīng),尤其是IO壓力集中在某些進(jìn)程上的場(chǎng)景。因?yàn)檫@種場(chǎng)景我們需要的滿足某個(gè)或者某幾個(gè)進(jìn)程的IO響應(yīng)速度,而不是讓所有的進(jìn)程公平的使用IO,比如數(shù)據(jù)庫(kù)應(yīng)用。deadline調(diào)度(最終期限調(diào)度)就是更適合上述場(chǎng)景的解決方案。deadline實(shí)現(xiàn)了四個(gè)隊(duì)列:其中兩個(gè)分別處理正常read和write,按扇區(qū)號(hào)排序,進(jìn)行正常io的合并處理以提高吞吐量。因?yàn)镮O請(qǐng)求可能會(huì)集中在某些磁盤(pán)位置,這樣會(huì)導(dǎo)致新來(lái)的請(qǐng)求一直被合并,可能會(huì)有其他磁盤(pán)位置的io請(qǐng)求被餓死。另外兩個(gè)處理超時(shí)read和write的隊(duì)列,按請(qǐng)求創(chuàng)建時(shí)間排序,如果有超時(shí)的請(qǐng)求出現(xiàn),就放進(jìn)這兩個(gè)隊(duì)列,調(diào)度算法保證超時(shí)(達(dá)到最終期限時(shí)間)的隊(duì)列中的請(qǐng)求會(huì)優(yōu)先被處理,防止掘歷請(qǐng)求被餓死。不久前,內(nèi)核還是默認(rèn)標(biāo)配四種算法,還有一種叫做as的算法(Anticipatoryscheduler),預(yù)測(cè)調(diào)度算法。一個(gè)高大上的名字,搞得我一度認(rèn)為L(zhǎng)inux內(nèi)核都會(huì)算命了。結(jié)果發(fā)現(xiàn),無(wú)非是在基于deadline算法做io調(diào)度的之前等一小會(huì)時(shí)間,如果這段時(shí)間內(nèi)有可以合并的io請(qǐng)求到來(lái),就可以合并處理,提高deadline調(diào)度的在順序讀寫(xiě)情況下的數(shù)據(jù)吞吐量。其實(shí)這根本不是啥預(yù)測(cè),我覺(jué)得不如叫撞大運(yùn)調(diào)度算法,當(dāng)然這種策略在某些特定場(chǎng)景差效果不錯(cuò)。但是在大多數(shù)場(chǎng)景下,這個(gè)調(diào)度不僅沒(méi)有提高吞吐量,還降低了響應(yīng)速度,所以內(nèi)核干脆把它從默認(rèn)配置里刪除了。畢竟Linux的宗旨是實(shí)用,而我們也就不再這個(gè)調(diào)度算法上多費(fèi)口舌了。1、cfq:完全公平隊(duì)列調(diào)度cfq是內(nèi)核默認(rèn)選擇的IO調(diào)度隊(duì)列,它在桌面應(yīng)用場(chǎng)景以及大多數(shù)常見(jiàn)應(yīng)用場(chǎng)景下都是很好的選擇。如何實(shí)現(xiàn)一個(gè)所謂的完全公平隊(duì)列(CompletelyFairQueueing)?首先我們要理解所謂的公平是對(duì)誰(shuí)的公平?從操作系統(tǒng)的角度來(lái)說(shuō),產(chǎn)生操作行為的主體都是進(jìn)程,所以這里的公平是針對(duì)每個(gè)進(jìn)程而言的,我們要試圖讓進(jìn)程可以公平的占用IO資源。那么如何讓進(jìn)程公平的占用IO資源?我們需要先理解什么是IO資源。當(dāng)我們衡量一個(gè)IO資源的時(shí)候,一般喜歡用的是兩個(gè)單位,一個(gè)是數(shù)據(jù)讀寫(xiě)的帶寬,另一個(gè)是數(shù)據(jù)讀寫(xiě)的IOPS。帶寬就是以時(shí)間為單位的讀寫(xiě)數(shù)據(jù)量,比如,100Mbyte/s。而IOPS是以時(shí)間為單位的讀寫(xiě)次數(shù)。在不同的讀寫(xiě)情境下,這兩個(gè)單位的表現(xiàn)可能不一樣,但是可以確定的是,兩個(gè)單位的任何一個(gè)達(dá)到了性能上限,都會(huì)成為IO的瓶頸。從機(jī)械硬盤(pán)的結(jié)構(gòu)考慮,如果讀寫(xiě)是順序讀寫(xiě),那么IO的表現(xiàn)是可以通過(guò)比較少的IOPS達(dá)到較大的帶寬,因?yàn)榭梢院喜⒑芏郔O,也可以通過(guò)預(yù)讀等方式加速數(shù)據(jù)讀取效率。當(dāng)IO的表現(xiàn)是偏向于隨機(jī)讀寫(xiě)的時(shí)候,那么IOPS就會(huì)變得更大,IO的請(qǐng)求的合并可能性下降,當(dāng)每次io請(qǐng)求數(shù)據(jù)越少的時(shí)候,帶寬表現(xiàn)就會(huì)越低。從這里我們可以理解,針對(duì)進(jìn)程的IO資源的主要表現(xiàn)形式有兩個(gè):進(jìn)程在單位時(shí)間內(nèi)提交的IO請(qǐng)求個(gè)數(shù)和進(jìn)程占用IO的帶寬。其實(shí)無(wú)論哪個(gè),都是跟進(jìn)程分配的IO處理時(shí)間長(zhǎng)度緊密相關(guān)的。有時(shí)業(yè)務(wù)可以在較少I(mǎi)OPS的情況下占用較大帶寬,另外一些則可能在較大IOPS的情況下占用較少帶寬,所以對(duì)進(jìn)程占用IO的時(shí)間進(jìn)行調(diào)度才是相對(duì)最公平的。即,我不管你是IOPS高還是帶寬占用高,到了時(shí)間咱就換下一個(gè)進(jìn)程處理,你愛(ài)咋樣咋樣。所以,cfq就是試圖給所有進(jìn)程分配等同的塊設(shè)備使用的時(shí)間片,進(jìn)程在時(shí)間片內(nèi),可以將產(chǎn)生的IO請(qǐng)求提交給塊設(shè)備進(jìn)行處理,時(shí)間片結(jié)束,進(jìn)程的請(qǐng)求將排進(jìn)它自己的隊(duì)列,等待下次調(diào)度的時(shí)候進(jìn)行處理。這就是cfq的基本原理。當(dāng)然,現(xiàn)實(shí)生活中不可能有真正的“公平”,常見(jiàn)的應(yīng)用場(chǎng)景下,我們很肯能需要人為的對(duì)進(jìn)程的IO占用進(jìn)行人為指定優(yōu)先級(jí),這就像對(duì)進(jìn)程的CPU占用設(shè)置優(yōu)先級(jí)的概念一樣。所以,除了針對(duì)時(shí)間片進(jìn)行公平隊(duì)列調(diào)度外,cfq還提供了優(yōu)先級(jí)支持。每個(gè)進(jìn)程都可以設(shè)置一個(gè)IO優(yōu)先級(jí),cfq會(huì)根據(jù)這個(gè)優(yōu)先級(jí)的設(shè)置情況作為調(diào)度時(shí)的重要參考因素。優(yōu)先級(jí)首先分成三大類(lèi):RT、BE、IDLE,它們分別是實(shí)時(shí)(RealTime)、更佳效果(BestTry)和閑置(Idle)三個(gè)類(lèi)別,對(duì)每個(gè)類(lèi)別的IO,cfq都使用不同的策略進(jìn)行處理。另外,RT和BE類(lèi)別中,分別又再劃分了8個(gè)子優(yōu)先級(jí)實(shí)現(xiàn)更細(xì)節(jié)的QOS需求,而IDLE只有一個(gè)子優(yōu)先級(jí)。另外,我們都知道內(nèi)核默認(rèn)對(duì)存儲(chǔ)的讀寫(xiě)都是經(jīng)過(guò)緩存(buffer/cache)的,在這種情況下,cfq是無(wú)法區(qū)分當(dāng)前處理的請(qǐng)求是來(lái)自哪一個(gè)進(jìn)程的。只有在進(jìn)程使用同步方式(syncread或者syncwirte)或者直接IO(DirectIO)方式進(jìn)行讀寫(xiě)的時(shí)候,cfq才能區(qū)分出IO請(qǐng)求來(lái)自哪個(gè)進(jìn)程。所以,除了針對(duì)每個(gè)進(jìn)程實(shí)現(xiàn)的IO隊(duì)列以外,還實(shí)現(xiàn)了一個(gè)公共的隊(duì)列用來(lái)處理異步請(qǐng)求。當(dāng)前內(nèi)核已經(jīng)實(shí)現(xiàn)了針對(duì)IO資源的cgroup資源隔離,所以在以上體系的基礎(chǔ)上,cfq也實(shí)現(xiàn)了針對(duì)cgroup的調(diào)度支持??偟膩?lái)說(shuō),cfq用了一系列的數(shù)據(jù)結(jié)構(gòu)實(shí)現(xiàn)了以上所有復(fù)雜功能的支持,大家可以通過(guò)源代碼看到其相關(guān)實(shí)現(xiàn),文件在源代碼目錄下的block/cfq-iosched.c。1.1cfq設(shè)計(jì)原理在此,我們對(duì)整體數(shù)據(jù)結(jié)構(gòu)做一個(gè)簡(jiǎn)要描述:首先,cfq通過(guò)一個(gè)叫做cfq_data的數(shù)據(jù)結(jié)構(gòu)維護(hù)了整個(gè)調(diào)度器流程。在一個(gè)支持了cgroup功能的cfq中,全部進(jìn)程被分成了若干個(gè)contralgroup進(jìn)行管理。每個(gè)cgroup在cfq中都有一個(gè)cfq_group的結(jié)構(gòu)進(jìn)行描述,所有的cgroup都被作為一個(gè)調(diào)度對(duì)象放進(jìn)一個(gè)紅黑樹(shù)中,并以vdisktime為key進(jìn)行排序。vdisktime這個(gè)時(shí)間紀(jì)錄的是當(dāng)前cgroup所占用的io時(shí)間,每次對(duì)cgroup進(jìn)行調(diào)度時(shí),總是通過(guò)紅黑樹(shù)選擇當(dāng)前vdisktime時(shí)間最少的cgroup進(jìn)行處理,以保證所有cgroups之間的IO資源占用“公平”。當(dāng)然我們知道,cgroup是可以對(duì)blkio進(jìn)行資源比例分配的,其作用原理就是,分配比例大的cgroup占用vdisktime時(shí)間增長(zhǎng)較慢,分配比例小的vdisktime時(shí)間增長(zhǎng)較快,快慢與分配比例成正比。這樣就做到了不同的cgroup分配的IO比例不一樣,并且在cfq的角度看來(lái)依然是“公平“的。選擇好了需要處理的cgroup(cfq_group)之后,調(diào)度器需要決策選擇下一步的service_tree。service_tree這個(gè)數(shù)據(jù)結(jié)構(gòu)對(duì)應(yīng)的都是一系列的紅黑樹(shù),主要目的是用來(lái)實(shí)現(xiàn)請(qǐng)求優(yōu)先級(jí)分類(lèi)的,就是RT、BE、IDLE的分類(lèi)。每一個(gè)cfq_group都維護(hù)了7個(gè)service_trees,其定義如下:其中service_tree_idle就是用來(lái)給IDLE類(lèi)型的請(qǐng)求進(jìn)行排隊(duì)用的紅黑樹(shù)。而上面二維數(shù)組,首先之一個(gè)維度針對(duì)RT和BE分別各實(shí)現(xiàn)了一個(gè)數(shù)組,每一個(gè)數(shù)組中都維護(hù)了三個(gè)紅黑樹(shù),分別對(duì)應(yīng)三種不同子類(lèi)型的請(qǐng)求,分別是:SYNC、SYNC_NOIDLE以及ASYNC。我們可以認(rèn)為SYNC相當(dāng)于SYNC_IDLE并與SYNC_NOIDLE對(duì)應(yīng)。idling是cfq在設(shè)計(jì)上為了盡量合并連續(xù)的IO請(qǐng)求以達(dá)到提高吞吐量的目的而加入的機(jī)制,我們可以理解為是一種“空轉(zhuǎn)”等待機(jī)制??辙D(zhuǎn)是指,當(dāng)一個(gè)隊(duì)列處理一個(gè)請(qǐng)求結(jié)束后,會(huì)在發(fā)生調(diào)度之前空等一小會(huì)時(shí)間,如果下一個(gè)請(qǐng)求到來(lái),則可以減少磁頭尋址,繼續(xù)處理順序的IO請(qǐng)求。為了實(shí)現(xiàn)這個(gè)功能,cfq在service_tree這層數(shù)據(jù)結(jié)構(gòu)這實(shí)現(xiàn)了SYNC隊(duì)列,如果請(qǐng)求是同步順序請(qǐng)求,就入隊(duì)這個(gè)servicetree,如果請(qǐng)求是同步隨機(jī)請(qǐng)求,則入隊(duì)SYNC_NOIDLE隊(duì)列,以判斷下一個(gè)請(qǐng)求是否是順序請(qǐng)求。所有的異步寫(xiě)操作請(qǐng)求將入隊(duì)ASYNC的servicetree,并且針對(duì)這個(gè)隊(duì)列沒(méi)有空轉(zhuǎn)等待機(jī)制。此外,cfq還對(duì)SSD這樣的硬盤(pán)有特殊調(diào)整,當(dāng)cfq發(fā)現(xiàn)存儲(chǔ)設(shè)備是一個(gè)ssd硬盤(pán)這樣的隊(duì)列深度更大的設(shè)備時(shí),所有針對(duì)單獨(dú)隊(duì)列的空轉(zhuǎn)都將不生效,所有的IO請(qǐng)求都將入隊(duì)SYNC_NOIDLE這個(gè)servicetree。每一個(gè)servicetree都對(duì)應(yīng)了若干個(gè)cfq_queue隊(duì)列,每個(gè)cfq_queue隊(duì)列對(duì)應(yīng)一個(gè)進(jìn)程,這個(gè)我們后續(xù)再詳細(xì)說(shuō)明。cfq_group還維護(hù)了一個(gè)在cgroup內(nèi)部所有進(jìn)程公用的異步IO請(qǐng)求隊(duì)列,其結(jié)構(gòu)如下:異步請(qǐng)求也分成了RT、BE、IDLE這三類(lèi)進(jìn)行處理,每一類(lèi)對(duì)應(yīng)一個(gè)cfq_queue進(jìn)行排隊(duì)。BE和RT也實(shí)現(xiàn)了優(yōu)先級(jí)的支持,每一個(gè)類(lèi)型有IOPRIO_BE_NR這么多個(gè)優(yōu)先級(jí),這個(gè)值定義為8,數(shù)組下標(biāo)為0-7。我們目前分析的內(nèi)核代碼版本為L(zhǎng)inux4.4,可以看出,從cfq的角度來(lái)說(shuō),已經(jīng)可以實(shí)現(xiàn)異步IO的cgroup支持了,我們需要定義一下這里所謂異步IO的含義,它僅僅表示從內(nèi)存的buffer/cache中的數(shù)據(jù)同步到硬盤(pán)的IO請(qǐng)求,而不是aio(man7aio)或者linux的native異步io以及l(fā)ibaio機(jī)制,實(shí)際上這些所謂的“異步”IO機(jī)制,在內(nèi)核中都是同步實(shí)現(xiàn)的(本質(zhì)上馮諾伊曼計(jì)算機(jī)沒(méi)有真正的“異步”機(jī)制)。我們?cè)谏厦嬉呀?jīng)說(shuō)明過(guò),由于進(jìn)程正常情況下都是將數(shù)據(jù)先寫(xiě)入buffer/cache,所以這種異步IO都是統(tǒng)一由cfq_group中的async請(qǐng)求隊(duì)列處理的。那么為什么在上面的service_tree中還要實(shí)現(xiàn)和一個(gè)ASYNC的類(lèi)型呢?這當(dāng)然是為了支持區(qū)分進(jìn)程的異步IO并使之可以“完全公平”做準(zhǔn)備嘍。實(shí)際上在最新的cgroupv2的blkio體系中,內(nèi)核已經(jīng)支持了針對(duì)bufferIO的cgroup限速支持,而以上這些可能容易混淆的一堆類(lèi)型,都是在新的體系下需要用到的類(lèi)型標(biāo)記。新體系的復(fù)雜度更高了,功能也更加強(qiáng)大,但是大家先不要著急,正式的cgroupv2體系,在Linux4.5發(fā)布的時(shí)候會(huì)正式跟大家見(jiàn)面。我們繼續(xù)選擇service_tree的過(guò)程,三種優(yōu)先級(jí)類(lèi)型的service_tree的選擇就是根據(jù)類(lèi)型的優(yōu)先級(jí)來(lái)做選擇的,RT優(yōu)先級(jí)更高,BE其次,IDLE更低。就是說(shuō),RT里有,就會(huì)一直處理RT,RT沒(méi)了再處理BE。每個(gè)service_tree對(duì)應(yīng)一個(gè)元素為cfq_queue排隊(duì)的紅黑樹(shù),而每個(gè)cfq_queue就是內(nèi)核為進(jìn)程(線程)創(chuàng)建的請(qǐng)求隊(duì)列。每一個(gè)cfq_queue都會(huì)維護(hù)一個(gè)rb_key的變量,這個(gè)變量實(shí)際上就是這個(gè)隊(duì)列的IO服務(wù)時(shí)間(servicetime)。這里還是通過(guò)紅黑樹(shù)找到servicetime時(shí)間最短的那個(gè)cfq_queue進(jìn)行服務(wù),以保證“完全公平”。選擇好了cfq_queue之后,就要開(kāi)始處理這個(gè)隊(duì)列里的IO請(qǐng)求了。這里的調(diào)度方式基本跟deadline類(lèi)似。cfq_queue會(huì)對(duì)進(jìn)入隊(duì)列的每一個(gè)請(qǐng)求進(jìn)行兩次入隊(duì),一個(gè)放進(jìn)fifo中,另一個(gè)放進(jìn)按訪問(wèn)扇區(qū)順序作為key的紅黑樹(shù)中。默認(rèn)從紅黑樹(shù)中取請(qǐng)求進(jìn)行處理,當(dāng)請(qǐng)求的延時(shí)時(shí)間達(dá)到deadline時(shí),就從紅黑樹(shù)中取等待時(shí)間最長(zhǎng)的進(jìn)行處理,以保證請(qǐng)求不被餓死。這就是整個(gè)cfq的調(diào)度流程,當(dāng)然其中還有很多細(xì)枝末節(jié)沒(méi)有交代,比如合并處理以及順序處理等等。1.2cfq的參數(shù)調(diào)整理解整個(gè)調(diào)度流程有助于我們決策如何調(diào)整cfq的相關(guān)參數(shù)。所有cfq的可調(diào)參數(shù)都可以在/sys/class/block/sda/queue/iosched/目錄下找到,當(dāng)然,在你的系統(tǒng)上,請(qǐng)將sda替換為相應(yīng)的磁盤(pán)名稱(chēng)。我們來(lái)看一下都有什么:這些參數(shù)部分是跟機(jī)械硬盤(pán)磁頭尋道方式有關(guān)的,如果其說(shuō)明你看不懂,請(qǐng)先補(bǔ)充相關(guān)知識(shí):back_seek_max:磁頭可以向后尋址的更大范圍,默認(rèn)值為16M。back_seek_penalty:向后尋址的懲罰系數(shù)。這個(gè)值是跟向前尋址進(jìn)行比較的。以上兩個(gè)是為了防止磁頭尋道發(fā)生抖動(dòng)而導(dǎo)致尋址過(guò)慢而設(shè)置的?;舅悸肥沁@樣,一個(gè)io請(qǐng)求到來(lái)的時(shí)候,cfq會(huì)根據(jù)其尋址位置預(yù)估一下其磁頭尋道成本。設(shè)置一個(gè)更大值back_seek_max,對(duì)于請(qǐng)求所訪問(wèn)的扇區(qū)號(hào)在磁頭后方的請(qǐng)求,只要尋址范圍沒(méi)有超過(guò)這個(gè)值,cfq會(huì)像向前尋址的請(qǐng)求一樣處理它。再設(shè)置一個(gè)評(píng)估成本的系數(shù)back_seek_penalty,相對(duì)于磁頭向前尋址,向后尋址的距離為1/2(1/back_seek_penalty)時(shí),cfq認(rèn)為這兩個(gè)請(qǐng)求尋址的代價(jià)是相同。這兩個(gè)參數(shù)實(shí)際上是cfq判斷請(qǐng)求合并處理的條件限制,凡事復(fù)合這個(gè)條件的請(qǐng)求,都會(huì)盡量在本次請(qǐng)求處理的時(shí)候一起合并處理。fifo_expire_async:設(shè)置異步請(qǐng)求的超時(shí)時(shí)間。同步請(qǐng)求和異步請(qǐng)求是區(qū)分不同隊(duì)列處理的,cfq在調(diào)度的時(shí)候一般情況都會(huì)優(yōu)先處理同步請(qǐng)求,之后再處理異步請(qǐng)求,除非異步請(qǐng)求符合上述合并處理的條件限制范圍內(nèi)。當(dāng)本進(jìn)程的隊(duì)列被調(diào)度時(shí),cfq會(huì)優(yōu)先檢查是否有異步請(qǐng)求超時(shí),就是超過(guò)fifo_expire_async參數(shù)的限制。如果有,則優(yōu)先發(fā)送一個(gè)超時(shí)的請(qǐng)求,其余請(qǐng)求仍然按照優(yōu)先級(jí)以及扇區(qū)編號(hào)大小來(lái)處理。fifo_expire_sync:這個(gè)參數(shù)跟上面的類(lèi)似,區(qū)別是用來(lái)設(shè)置同步請(qǐng)求的超時(shí)時(shí)間。slice_idle:參數(shù)設(shè)置了一個(gè)等待時(shí)間。這讓cfq在切換cfq_queue或servicetree的時(shí)候等待一段時(shí)間,目的是提高機(jī)械硬盤(pán)的吞吐量。一般情況下,來(lái)自同一個(gè)cfq_queue或者servicetree的IO請(qǐng)求的尋址局部性更好,所以這樣可以減少磁盤(pán)的尋址次數(shù)。這個(gè)值在機(jī)械硬盤(pán)上默認(rèn)為非零。當(dāng)然在固態(tài)硬盤(pán)或者硬RAID設(shè)備上設(shè)置這個(gè)值為非零會(huì)降低存儲(chǔ)的效率,因?yàn)楣虘B(tài)硬盤(pán)沒(méi)有磁頭尋址這個(gè)概念,所以在這樣的設(shè)備上應(yīng)該設(shè)置為0,關(guān)閉此功能。group_idle:這個(gè)參數(shù)也跟上一個(gè)參數(shù)類(lèi)似,區(qū)別是當(dāng)cfq要切換cfq_group的時(shí)候會(huì)等待一段時(shí)間。在cgroup的場(chǎng)景下,如果我們沿用slice_idle的方式,那么空轉(zhuǎn)等待可能會(huì)在cgroup組內(nèi)每個(gè)進(jìn)程的cfq_queue切換時(shí)發(fā)生。這樣會(huì)如果這個(gè)進(jìn)程一直有請(qǐng)求要處理的話,那么直到這個(gè)cgroup的配額被耗盡,同組中的其它進(jìn)程也可能無(wú)法被調(diào)度到。這樣會(huì)導(dǎo)致同組中的其它進(jìn)程餓死而產(chǎn)生IO性能瓶頸。在這種情況下,我們可以將slice_idle=0而group_idle=8。這樣空轉(zhuǎn)等待就是以cgroup為單位進(jìn)行的,而不是以cfq_queue的進(jìn)程為單位進(jìn)行,以防止上述問(wèn)題產(chǎn)生。low_latency:這個(gè)是用來(lái)開(kāi)啟或關(guān)閉cfq的低延時(shí)(lowlatency)模式的開(kāi)關(guān)。當(dāng)這個(gè)開(kāi)關(guān)打開(kāi)時(shí),cfq將會(huì)根據(jù)target_latency的參數(shù)設(shè)置來(lái)對(duì)每一個(gè)進(jìn)程的分片時(shí)間(slicetime)進(jìn)行重新計(jì)算。這將有利于對(duì)吞吐量的公平(默認(rèn)是對(duì)時(shí)間片分配的公平)。關(guān)閉這個(gè)參數(shù)(設(shè)置為0)將忽略target_latency的值。這將使系統(tǒng)中的進(jìn)程完全按照時(shí)間片方式進(jìn)行IO資源分配。這個(gè)開(kāi)關(guān)默認(rèn)是打開(kāi)的。我們已經(jīng)知道cfq設(shè)計(jì)上有“空轉(zhuǎn)”(idling)這個(gè)概念,目的是為了可以讓連續(xù)的讀寫(xiě)操作盡可能多的合并處理,減少磁頭的尋址操作以便增大吞吐量。如果有進(jìn)程總是很快的進(jìn)行順序讀寫(xiě),那么它將因?yàn)閏fq的空轉(zhuǎn)等待命中率很高而導(dǎo)致其它需要處理IO的進(jìn)程響應(yīng)速度下降,如果另一個(gè)需要調(diào)度的進(jìn)程不會(huì)發(fā)出大量順序IO行為的話,系統(tǒng)中不同進(jìn)程IO吞吐量的表現(xiàn)就會(huì)很不均衡。就比如,系統(tǒng)內(nèi)存的cache中有很多臟頁(yè)要寫(xiě)回時(shí),桌面又要打開(kāi)一個(gè)瀏覽器進(jìn)行操作,這時(shí)臟頁(yè)寫(xiě)回的后臺(tái)行為就很可能會(huì)大量命中空轉(zhuǎn)時(shí)間,而導(dǎo)致瀏覽器的小量IO一直等待,讓用戶感覺(jué)瀏覽器運(yùn)行響應(yīng)速度變慢。這個(gè)low_latency主要是對(duì)這種情況進(jìn)行優(yōu)化的選項(xiàng),當(dāng)其打開(kāi)時(shí),系統(tǒng)會(huì)根據(jù)target_latency的配置對(duì)因?yàn)槊锌辙D(zhuǎn)而大量占用IO吞吐量的進(jìn)程進(jìn)行限制,以達(dá)到不同進(jìn)程IO占用的吞吐量的相對(duì)均衡。這個(gè)開(kāi)關(guān)比較合適在類(lèi)似桌面應(yīng)用的場(chǎng)景下打開(kāi)。target_latency:當(dāng)low_latency的值為開(kāi)啟狀態(tài)時(shí),cfq將根據(jù)這個(gè)值重新計(jì)算每個(gè)進(jìn)程分配的IO時(shí)間片長(zhǎng)度。quantum:這個(gè)參數(shù)用來(lái)設(shè)置每次從cfq_queue中處理多少個(gè)IO請(qǐng)求。在一個(gè)隊(duì)列處理事件周期中,超過(guò)這個(gè)數(shù)字的IO請(qǐng)求將不會(huì)被處理。這個(gè)參數(shù)只對(duì)同步的請(qǐng)求有效。slice_sync:當(dāng)一個(gè)cfq_queue隊(duì)列被調(diào)度處理時(shí),它可以被分配的處理總時(shí)間是通過(guò)這個(gè)值來(lái)作為一個(gè)計(jì)算參數(shù)指定的。公式為:time_slice=slice_sync+(slice_sync/5*(4-prio))。這個(gè)參數(shù)對(duì)同步請(qǐng)求有效。slice_async:這個(gè)值跟上一個(gè)類(lèi)似,區(qū)別是對(duì)異步請(qǐng)求有效。slice_async_rq:這個(gè)參數(shù)用來(lái)限制在一個(gè)slice的時(shí)間范圍內(nèi),一個(gè)隊(duì)列最多可以處理的異步請(qǐng)求個(gè)數(shù)。請(qǐng)求被處理的更大個(gè)數(shù)還跟相關(guān)進(jìn)程被設(shè)置的io優(yōu)先級(jí)有關(guān)。1.3cfq的IOPS模式我們已經(jīng)知道,默認(rèn)情況下cfq是以時(shí)間片方式支持的帶優(yōu)先級(jí)的調(diào)度來(lái)保證IO資源占用的公平。高優(yōu)先級(jí)的進(jìn)程將得到的時(shí)間片長(zhǎng)度,而低優(yōu)先級(jí)的進(jìn)程時(shí)間片相對(duì)較小。當(dāng)我們的存儲(chǔ)是一個(gè)高速并且支持NCQ(原生指令隊(duì)列)的設(shè)備的時(shí)候,我們更好可以讓其可以從多個(gè)cfq隊(duì)列中處理多路的請(qǐng)求,以便提升NCQ的利用率。此時(shí)使用時(shí)間片的分配方式分配資源就顯得不合時(shí)宜了,因?yàn)榛跁r(shí)間片的分配,同一時(shí)刻最多能處理的請(qǐng)求隊(duì)列只有一個(gè)。這時(shí),我們需要切換cfq的模式為IOPS模式。切換方式很簡(jiǎn)單,就是將slice_idle=0即可。內(nèi)核會(huì)自動(dòng)檢測(cè)你的存儲(chǔ)設(shè)備是否支持NCQ,如果支持的話cfq會(huì)自動(dòng)切換為IOPS模式。另外,在默認(rèn)的基于優(yōu)先級(jí)的時(shí)間片方式下,我們可以使用ionice命令來(lái)調(diào)整進(jìn)程的IO優(yōu)先級(jí)。進(jìn)程默認(rèn)分配的IO優(yōu)先級(jí)是根據(jù)進(jìn)程的nice值計(jì)算而來(lái)的,計(jì)算方法可以在manionice中看到,這里不再?gòu)U話。2、deadline:最終期限調(diào)度deadline調(diào)度算法相對(duì)cfq要簡(jiǎn)單很多。其設(shè)計(jì)目標(biāo)是:在保證請(qǐng)求按照設(shè)備扇區(qū)的順序進(jìn)行訪問(wèn)的同時(shí),兼顧其它請(qǐng)求不被餓死,要在一個(gè)最終期限前被調(diào)度到。我們知道磁頭對(duì)磁盤(pán)的尋道是可以進(jìn)行順序訪問(wèn)和隨機(jī)訪問(wèn)的,因?yàn)閷さ姥訒r(shí)時(shí)間的關(guān)系,順序訪問(wèn)時(shí)IO的吞吐量更大,隨機(jī)訪問(wèn)的吞吐量小。如果我們想為一個(gè)機(jī)械硬盤(pán)進(jìn)行吞吐量?jī)?yōu)化的話,那么就可以讓調(diào)度器按照盡量復(fù)合順序訪問(wèn)的IO請(qǐng)求進(jìn)行排序,之后請(qǐng)求以這樣的順序發(fā)送給硬盤(pán),就可以使IO的吞吐量更大。但是這樣做也有另一個(gè)問(wèn)題,就是如果此時(shí)出現(xiàn)了一個(gè)請(qǐng)求,它要訪問(wèn)的磁道離目前磁頭所在磁道很遠(yuǎn),應(yīng)用的請(qǐng)求又大量集中在目前磁道附近。導(dǎo)致大量請(qǐng)求一直會(huì)被合并和插隊(duì)處理,而那個(gè)要訪問(wèn)比較遠(yuǎn)磁道的請(qǐng)求將因?yàn)橐恢辈荒鼙徽{(diào)度而餓死。deadline就是這樣一種調(diào)度器,能在保證IO更大吞吐量的情況下,盡量使遠(yuǎn)端請(qǐng)求在一個(gè)期限內(nèi)被調(diào)度而不被餓死的調(diào)度器。linux libaio的介紹就聊到這里吧,感謝你花時(shí)間閱讀本站內(nèi)容,更多關(guān)于linux libaio,Linux下的高效異步IO:libaio詳解,面試 linux 文件系統(tǒng)怎樣io到底層的信息別忘了在本站進(jìn)行查找喔。

四川成都云服務(wù)器租用托管【創(chuàng)新互聯(lián)】提供各地服務(wù)器租用,電信服務(wù)器托管、移動(dòng)服務(wù)器托管、聯(lián)通服務(wù)器托管,云服務(wù)器虛擬主機(jī)租用。成都機(jī)房托管咨詢:13518219792
創(chuàng)新互聯(lián)(www.cdcxhl.com)擁有10多年的服務(wù)器租用、服務(wù)器托管、云服務(wù)器、虛擬主機(jī)、網(wǎng)站系統(tǒng)開(kāi)發(fā)經(jīng)驗(yàn)、開(kāi)啟建站+互聯(lián)網(wǎng)銷(xiāo)售服務(wù),與企業(yè)客戶共同成長(zhǎng),共創(chuàng)價(jià)值。


文章標(biāo)題:Linux下的高效異步IO:libaio詳解(linuxlibaio)
文章地址:http://www.dlmjj.cn/article/cdpidio.html