最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會員登陸 & 注冊

一文帶你玩轉(zhuǎn)Linux文件系統(tǒng)之-通用塊處理層!

2022-05-12 15:55 作者:補給站Linux內(nèi)核  | 我要投稿

概述

  • 由于不同塊設(shè)備(如磁盤,機械硬盤等)有著不同的設(shè)備驅(qū)動程序,為了讓文件系統(tǒng)有統(tǒng)一的讀寫塊設(shè)備接口,Linux實現(xiàn)了一個 通用塊層。如下圖中的紅色部分:


  • 通用塊層 的引入為了提供一個統(tǒng)一的接口讓文件系統(tǒng)實現(xiàn)者使用,而不用關(guān)心不同設(shè)備驅(qū)動程序的差異,這樣實現(xiàn)出來的文件系統(tǒng)就能用于任何的塊設(shè)備。

  • 通用塊層 將對不同塊設(shè)備的操作轉(zhuǎn)換成對邏輯數(shù)據(jù)塊的操作,也就是將不同的塊設(shè)備都抽象成是一個數(shù)據(jù)塊數(shù)組,而文件系統(tǒng)就是對這些數(shù)據(jù)塊進行管理。如下圖:

注意:不同的文件系統(tǒng)可能對邏輯數(shù)據(jù)塊定義的大小不一樣,比如 ext2文件系統(tǒng) 的邏輯數(shù)據(jù)塊大小為 4KB。


  • 通過對設(shè)備進行抽象后,不管是磁盤還是機械硬盤,對于文件系統(tǒng)都可以使用相同的接口對邏輯數(shù)據(jù)塊進行讀寫操作。

【文章福利】小編推薦自己的Linux內(nèi)核技術(shù)交流群:【891587639】整理了一些個人覺得比較好的學(xué)習(xí)書籍、視頻資料共享在群文件里面,有需要的可以自行添加哦?。?!前100名進群領(lǐng)取,額外贈送一份價值699的內(nèi)核資料包(含視頻教程、電子書、實戰(zhàn)項目及代碼)? ??


通用塊讀寫接口

  • 通用塊層 提供了 ll_rw_block() 函數(shù)對邏輯塊進行讀寫操作,ll_rw_block() 函數(shù)的原型如下:

  • 在分析 ll_rw_block() 函數(shù)前,我們先來介紹一下 buffer_head 這個結(jié)構(gòu),因為要理解 ll_rw_block() 函數(shù)必須先了解 buffer_head 結(jié)構(gòu)。

  • struct buffer_head 結(jié)構(gòu)代表一個要進行讀或者寫的數(shù)據(jù)塊,其定義如下:

  • 為了讓讀者更加清晰,上面忽略了 buffer_head 結(jié)構(gòu)的某些字段,上面比較重要的是 b_blocknr 字段和 b_size 字段, b_blocknr 字段指定了要讀寫的數(shù)據(jù)塊號,而 b_size 字段指定了數(shù)據(jù)塊的大小。還有就是 b_rdev 字段,其指定了數(shù)據(jù)塊所屬的設(shè)備。

  • 有了 buffer_head 結(jié)構(gòu),就可以對數(shù)據(jù)塊進行讀寫操作。接下來,我們看看 ll_rw_block() 函數(shù)的實現(xiàn):

  • 下面介紹一下 ll_rw_block() 函數(shù)各個參數(shù)的作用:

  1. rw:要進行的讀或者寫操作,一般可選的值為 READ、WRITE 或者 READA 等。

  2. nr:bhs 數(shù)組的大小。

  3. bhs:要進行讀寫操作的數(shù)據(jù)塊數(shù)組。

  • ll_rw_block() 函數(shù)的實現(xiàn)比較簡單,遍歷 bhs 數(shù)組,并且對所有的 buffer_head 進行上鎖和增加其計數(shù)器,然后調(diào)用 submit_bh() 函數(shù)把其提交到 IO調(diào)度層 進行I/O操作。

  • 我們接著看看 submit_bh() 函數(shù)的實現(xiàn):

  • 數(shù)據(jù)塊是 通用塊層 的概念,而真實的塊設(shè)備是以扇區(qū)作為讀寫單元的。所以在進行IO操作前,必須將數(shù)據(jù)塊號轉(zhuǎn)換成真正的扇區(qū)號,而代碼 bh->b_blocknr * count 就是用于將數(shù)據(jù)塊號轉(zhuǎn)換成扇區(qū)號。轉(zhuǎn)換成扇區(qū)號后,submit_bh() 函數(shù)接著調(diào)用 generic_make_request() 進行下一步的操作。

  • 我們接著分析 generic_make_request() 函數(shù)的實現(xiàn):

  • 每一個塊設(shè)備都有一個類型為 request_queue_t 的I/O請求隊列,而 blk_get_queue() 函數(shù)用于獲取塊設(shè)備對應(yīng)的I/O請求隊列,然后調(diào)用I/O請求隊列的 mark_request_fn() 方法把I/O請求添加到隊列中。

  • 那么I/O請求隊列的 mark_request_fn() 方法到底是什么呢?這個方法由塊設(shè)備驅(qū)動提供,也可以通過調(diào)用 blk_init_queue() 函數(shù)設(shè)置為默認的 __make_request() 方法。我們主要分析默認的 __make_request() 方法:

  • __make_request() 函數(shù)首先通過調(diào)用 elevator->elevator_merge_fn() 方法嘗試將當前I/O請求與其他正在排隊的I/O請求進行合并,因為如果當前I/O請求與正在排隊的I/O請求相鄰,那么就可以合并為一個I/O請求,從而減少對設(shè)備I/O請求的次數(shù)。

  • 如果不能與排隊的I/O請求進行合并,那么就調(diào)用 get_request() 函數(shù)申請一個I/O請求對象,然后初始化此對象各個字段,再通過調(diào)用 add_request() 函數(shù)把I/O請求對象添加到I/O請求隊列中。add_request() 函數(shù)實現(xiàn)如下:

  • add_request() 函數(shù)的實現(xiàn)非常簡單,首先調(diào)用 drive_stat_acct() 函數(shù)更新統(tǒng)計信息,然后調(diào)用 list_add() 函數(shù)把I/O請求添加到I/O請求隊列中。

執(zhí)行I/O請求

  • ll_rw_block() 函數(shù)只是把I/O請求添加到設(shè)備的I/O請求隊列中,那么I/O請求隊列中的I/O請求什么時候會執(zhí)行呢?答案就是當調(diào)用 run_task_queue(&tq_disk) 函數(shù)時。

  • run_task_queue() 函數(shù)是 Linux 用于運行任務(wù)隊列的入口,而 tq_disk 隊列就是塊設(shè)備I/O的任務(wù)隊列。當執(zhí)行 run_task_queue(&tq_disk) 函數(shù)時,便會處理 tq_disk 任務(wù)隊列中的例程。

  • 當調(diào)用 ll_rw_block() 函數(shù)添加I/O請求時,會觸發(fā)調(diào)用 generic_plug_device() 函數(shù),而 generic_plug_device() 函數(shù)會把設(shè)備的I/O請求隊列添加到 tq_disk 任務(wù)隊列中, generic_plug_device() 函數(shù)實現(xiàn)如下:

通過 Linux 的任務(wù)隊列機制,設(shè)備的I/O請求隊列將會被執(zhí)行。執(zhí)行I/O請求主要是由塊設(shè)備驅(qū)動完成,在塊設(shè)備驅(qū)動程序初始化時可以通過調(diào)用 blk_init_queue() 函數(shù)指定處理I/O請求隊列的方法。blk_init_queue() 函數(shù)原型如下:

參數(shù) rfn 就是處理I/O請求隊列的例程函數(shù)。


一文帶你玩轉(zhuǎn)Linux文件系統(tǒng)之-通用塊處理層!的評論 (共 條)

分享到微博請遵守國家法律
安新县| 六安市| 合江县| 怀安县| 吉木乃县| 集贤县| 巴林右旗| 且末县| 灵山县| 明溪县| 肃宁县| 通江县| 兖州市| 宝山区| 新营市| 泸溪县| 托克托县| 泸州市| 新民市| 元朗区| 伊川县| 香格里拉县| 龙山县| 元阳县| 克山县| 荔波县| 淮南市| 长顺县| 梓潼县| 海淀区| 全南县| 盈江县| 元氏县| 杨浦区| 安达市| 祁东县| 昆明市| 汉川市| 沾益县| 赤壁市| 防城港市|