如何實(shí)現(xiàn)linux塊設(shè)備IO棧淺析,很多新手對(duì)此不是很清楚,為了幫助大家解決這個(gè)難題,下面小編將為大家詳細(xì)講解,有這方面需求的人可以來(lái)學(xué)習(xí)下,希望你能有所收獲。
為敘永等地區(qū)用戶提供了全套網(wǎng)頁(yè)設(shè)計(jì)制作服務(wù),及敘永網(wǎng)站建設(shè)行業(yè)解決方案。主營(yíng)業(yè)務(wù)為成都網(wǎng)站建設(shè)、成都網(wǎng)站設(shè)計(jì)、敘永網(wǎng)站設(shè)計(jì),以傳統(tǒng)方式定制建設(shè)網(wǎng)站,并提供域名空間備案等一條龍服務(wù),秉承以專業(yè)、用心的態(tài)度為用戶提供真誠(chéng)的服務(wù)。我們深信只要達(dá)到每一位用戶的要求,就會(huì)得到認(rèn)可,從而選擇與我們長(zhǎng)期合作。這樣,我們也可以走得更遠(yuǎn)!
塊存儲(chǔ),簡(jiǎn)單來(lái)說(shuō)就是使用塊設(shè)備為系統(tǒng)提供存儲(chǔ)服務(wù)。塊存儲(chǔ)分多種類型,有單機(jī)塊存儲(chǔ),網(wǎng)絡(luò)存儲(chǔ)(如NAS,SAN等),分布式塊存儲(chǔ)(目前主流的如AWS的EBS,青云的云硬盤,阿里云的云磁盤,網(wǎng)易云硬盤等)。通常塊存儲(chǔ)的表現(xiàn)形式就是一塊設(shè)備,用戶看到的就是類似于sda,sdb這樣的邏輯設(shè)備。本文主要介紹Linux塊設(shè)備,對(duì)Linux的塊設(shè)備I/O棧進(jìn)行分析。
塊設(shè)備將信息存儲(chǔ)在固定大小的塊中,每個(gè)塊都有自己的地址。對(duì)操作系統(tǒng)而言,塊設(shè)備是以字符設(shè)備的外觀展現(xiàn)的,例如/dev/sda,雖然對(duì)這種字符設(shè)備可以按照字節(jié)為單位訪問(wèn),但是實(shí)際上到塊設(shè)備上卻是以塊為單位(最小512byte,即一個(gè)扇區(qū)),這之間的轉(zhuǎn)換是由操作系統(tǒng)來(lái)實(shí)現(xiàn)的。
下面介紹幾個(gè)塊設(shè)備的基本概念:
1)扇區(qū):磁盤盤片上的扇形區(qū)域,邏輯化數(shù)據(jù),方便管理磁盤空間,是硬件設(shè)備數(shù)據(jù)傳送的基本單位,一般512Byte;
2)塊:塊是VFS和文件系統(tǒng)數(shù)據(jù)傳送的基本單位,必須是扇區(qū)的整數(shù)倍,格式化文件系統(tǒng)時(shí),可以指定塊大?。ㄒ话?12,1024,2048,4096字節(jié));
3)段:一個(gè)內(nèi)存頁(yè)或者內(nèi)存頁(yè)中的一部分,包含一些相鄰磁盤扇區(qū)中的數(shù)據(jù);磁盤的每個(gè)I/O操作就是在磁盤與一些RAM單元之間相互傳一些相鄰扇區(qū)的內(nèi)容,大多數(shù)情況下,磁盤控制器采用DMA方式進(jìn)行數(shù)據(jù)傳送。如果不同的段在RAM中相應(yīng)的頁(yè)框是連續(xù)的并且在磁盤上相應(yīng)的數(shù)據(jù)塊也是相鄰的,就可以在通用塊層合并它們,產(chǎn)生更大的內(nèi)存區(qū)域,這個(gè)區(qū)域稱為物理段。
通常情況下,我們是通過(guò)文件系統(tǒng)來(lái)訪問(wèn)塊設(shè)備,也可以直接使用裸設(shè)備,通過(guò)指定偏移和大小來(lái)讀寫裸設(shè)備。
常見(jiàn)的塊存儲(chǔ)設(shè)備就是物理磁盤,在Linux系統(tǒng)下,還提供基于其他塊設(shè)備之上的邏輯設(shè)備,如Device Mapper,軟RAID等。
介紹塊設(shè)備的I/O棧之前,我們先來(lái)了解一下塊I/O棧的幾個(gè)基本概念。
1)bio:bio是通用塊層I/O請(qǐng)求的數(shù)據(jù)結(jié)構(gòu),表示上層提交的I/O請(qǐng)求,一個(gè)bio包含多個(gè)page,這些page必須對(duì)應(yīng)磁盤上一段連續(xù)的空間。由于文件在磁盤上并不連續(xù)存放,文件I/O提交到塊設(shè)備之前,極有可能被拆成多個(gè)bio結(jié)構(gòu);
2)request:表示塊設(shè)備驅(qū)動(dòng)層I/O請(qǐng)求,經(jīng)由I/O調(diào)度層轉(zhuǎn)換后的I/O請(qǐng)求,將會(huì)發(fā)到塊設(shè)備驅(qū)動(dòng)層進(jìn)行處理;
3)request_queue: 維護(hù)塊設(shè)備驅(qū)動(dòng)層I/O請(qǐng)求的隊(duì)列,所有的request都插入到該隊(duì)列,每個(gè)磁盤設(shè)備都只有一個(gè)queue(多個(gè)分區(qū)也只有一個(gè));
這3個(gè)結(jié)構(gòu)的關(guān)系如下圖示:一個(gè)request_queue中包含多個(gè)request,每個(gè)request可能包含多個(gè)bio,請(qǐng)求的合并就是根據(jù)各種原則將多個(gè)bio加入到同一個(gè)requesst中。
如圖所示是塊設(shè)備的I/O棧,其中的紅色文字表示關(guān)鍵I/O路徑的函數(shù)。
為了描述I/O處理流程,先介紹一下Direct I/O和緩存I/O的區(qū)別:
1)Direct I/O繞過(guò)page cache,而緩存I/O都是寫到page cache里就表示寫請(qǐng)求完成,然后由文件系統(tǒng)的刷臟頁(yè)機(jī)制把數(shù)據(jù)刷到磁盤。因此,使用緩存I/O,掉電時(shí)有可能page cache里的臟數(shù)據(jù)未刷到磁盤上,造成數(shù)據(jù)丟失;
2)緩存I/O機(jī)制中,DMA方式可以將數(shù)據(jù)直接從磁盤讀到page cache中,或者將數(shù)據(jù)從page cache直接寫回到磁盤上,而不能直接在應(yīng)用程序地址空間和磁盤之間進(jìn)行數(shù)據(jù)傳輸,這樣的話,數(shù)據(jù)在傳輸過(guò)程中需要在應(yīng)用程序地址空間和page cache之間進(jìn)行多次數(shù)據(jù)拷貝操作,這些數(shù)據(jù)拷貝操作所帶來(lái)的CPU以及內(nèi)存開(kāi)銷是非常大的。而Direct I/O的優(yōu)點(diǎn)就是通過(guò)減少操作系統(tǒng)內(nèi)核緩沖區(qū)和應(yīng)用程序地址空間的數(shù)據(jù)拷貝次數(shù),降低了對(duì)文件讀取和寫入時(shí)所帶來(lái)的CPU的使用以及內(nèi)存帶寬的占用,但是Direct I/O的讀操作不能從page cache中獲取數(shù)據(jù),會(huì)直接從磁盤上讀取,帶來(lái)性能上的損失。一般Direct I/O與異步I/O結(jié)合起來(lái)使用提高性能。
3)Direct I/O要求用戶態(tài)的緩沖區(qū)對(duì)齊;
4)Direct I/O一般用于需要自己管理緩存的應(yīng)用如數(shù)據(jù)庫(kù)系統(tǒng)。
對(duì)于I/O的讀寫流程,邏輯比較復(fù)雜,這里以寫流程簡(jiǎn)單描述如下:
1)用戶調(diào)用系統(tǒng)調(diào)用write寫一個(gè)文件,會(huì)調(diào)到sys_write函數(shù);
2) 經(jīng)過(guò)VFS虛擬文件系統(tǒng)層,調(diào)用vfs_write, 如果是緩存寫方式,則寫入page cache,然后就返回,后續(xù)就是刷臟頁(yè)的流程;如果是Direct I/O的方式,就會(huì)走到do_blockdev_direct_IO的流程;
3)如果操作的設(shè)備是邏輯設(shè)備如LVM,MDRAID設(shè)備等,會(huì)進(jìn)入到對(duì)應(yīng)內(nèi)核模塊的處理函數(shù)里進(jìn)行一些處理,否則就直接構(gòu)造bio請(qǐng)求,調(diào)用submit_bio往具體的塊設(shè)備下發(fā)請(qǐng)求,submit_bio函數(shù)通過(guò)generic_make_request轉(zhuǎn)發(fā)bio,generic_make_request是一個(gè)循環(huán),其通過(guò)每個(gè)塊設(shè)備下注冊(cè)的q->make_request_fn函數(shù)與塊設(shè)備進(jìn)行交互;
4)請(qǐng)求下發(fā)到底層的塊設(shè)備上,調(diào)用塊設(shè)備請(qǐng)求處理函數(shù)__make_request進(jìn)行處理,在這個(gè)函數(shù)中就會(huì)調(diào)用blk_queue_bio,這個(gè)函數(shù)就是合并bio到request中,也就是I/O調(diào)度器的具體實(shí)現(xiàn):如果幾個(gè)bio要讀寫的區(qū)域是連續(xù)的,就合并到一個(gè)request;否則就創(chuàng)建一個(gè)新的request,把自己掛到這個(gè)request下。合并bio請(qǐng)求也是有限度的,如果合并后的請(qǐng)求超過(guò)閾值(在/sys/block/xxx/queue/max_sectors_kb里設(shè)置),就不能再合并成一個(gè)request了,而會(huì)新分配一個(gè)request;
5)接下來(lái)的I/O操作就與具體的物理設(shè)備有關(guān)了,交由相應(yīng)的塊設(shè)備驅(qū)動(dòng)程序進(jìn)行處理,這里以scsi設(shè)備為例說(shuō)明,queue隊(duì)列的處理函數(shù)q->request_fn對(duì)應(yīng)的scsi驅(qū)動(dòng)的就是scsi_request_fn函數(shù),將請(qǐng)求構(gòu)造成scsi指令下發(fā)到scsi設(shè)備進(jìn)行處理,處理完成后就會(huì)依次調(diào)用各層的回調(diào)函數(shù)進(jìn)行完成狀態(tài)的一些處理,最后返回給上層用戶。
在塊設(shè)備的I/O處理流程中,會(huì)涉及到兩種不同的處理方式:
1)request-based:這種處理方式下,會(huì)進(jìn)行bio合并到request(即I/O調(diào)度合并)的流程,最后才把請(qǐng)求下發(fā)到物理設(shè)備。目前使用的物理盤都是request-based的設(shè)備;
2)bio-based:在邏輯設(shè)備自己定義的request處理函數(shù)make_request_fn里進(jìn)行處理,然后調(diào)用generic_make_request下發(fā)到底層設(shè)備。ramdisk設(shè)備、大部分Device Mapper設(shè)備、virtio-blk都是bio-based;
下圖從Device Mapper的角度來(lái)說(shuō)明request-based和bio-based處理流程的區(qū)別。
一個(gè)需要注意的地方是,Device mapper目前只有multipath插件是request-based的,其他的如linear,strip都是bio-based,所以如果是linear DM設(shè)備上創(chuàng)建的一個(gè)文件系統(tǒng),對(duì)這個(gè)文件系統(tǒng)里的文件進(jìn)行讀寫,采用緩存I/O時(shí),即使刷臟頁(yè)時(shí)是連續(xù)的請(qǐng)求,在DM設(shè)備上也不會(huì)進(jìn)行合并,只會(huì)到底層的設(shè)備(如/dev/sdb)上才進(jìn)行合并。
看完上述內(nèi)容是否對(duì)您有幫助呢?如果還想對(duì)相關(guān)知識(shí)有進(jìn)一步的了解或閱讀更多相關(guān)文章,請(qǐng)關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道,感謝您對(duì)創(chuàng)新互聯(lián)的支持。
分享文章:如何實(shí)現(xiàn)linux塊設(shè)備IO棧淺析
標(biāo)題路徑:http://chinadenli.net/article0/ihdpoo.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站導(dǎo)航、網(wǎng)站營(yíng)銷、全網(wǎng)營(yíng)銷推廣、手機(jī)網(wǎng)站建設(shè)、動(dòng)態(tài)網(wǎng)站、自適應(yīng)網(wǎng)站
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)