新聞中心
linux 設(shè)備驅(qū)動(dòng)模型是 Linux 內(nèi)核開發(fā)中非常重要的一部分,它的作用是抽象硬件,為高級(jí)應(yīng)用程序提供接口,同時(shí)也為驅(qū)動(dòng)程序提供一種標(biāo)準(zhǔn)化的接口和規(guī)范。通過這種模型,我們可以像應(yīng)用程序一樣簡(jiǎn)單地和硬件進(jìn)行交互,而不是需要直接操作硬件。

成都創(chuàng)新互聯(lián)專注于磁縣網(wǎng)站建設(shè)服務(wù)及定制,我們擁有豐富的企業(yè)做網(wǎng)站經(jīng)驗(yàn)。 熱誠(chéng)為您提供磁縣營(yíng)銷型網(wǎng)站建設(shè),磁縣網(wǎng)站制作、磁縣網(wǎng)頁(yè)設(shè)計(jì)、磁縣網(wǎng)站官網(wǎng)定制、成都微信小程序服務(wù),打造磁縣網(wǎng)絡(luò)公司原創(chuàng)品牌,更為您提供磁縣網(wǎng)站排名全網(wǎng)營(yíng)銷落地服務(wù)。
本文將對(duì) Linux 設(shè)備驅(qū)動(dòng)模型作出詳細(xì)解析,包括它的原理、組織架構(gòu)、部件和 API 接口等方面。我們希望能夠幫助大家更全面的了解 Linux 的設(shè)備驅(qū)動(dòng)模型,以及如何使用該模型來(lái)編寫硬件驅(qū)動(dòng)程序。
一. 設(shè)備驅(qū)動(dòng)模型的原理
Linux 設(shè)備驅(qū)動(dòng)模型的核心原理是將設(shè)備抽象成一個(gè)標(biāo)準(zhǔn)框架,通過該框架,應(yīng)用程序和設(shè)備驅(qū)動(dòng)程序可以更高效地交互。在設(shè)備驅(qū)動(dòng)模型中,設(shè)備分為了兩個(gè)主要部分:實(shí)體和驅(qū)動(dòng)程序。實(shí)體是指設(shè)備的硬件實(shí)現(xiàn),而驅(qū)動(dòng)程序則是設(shè)備和應(yīng)用程序之間的中間件,用于將硬件的實(shí)現(xiàn)和應(yīng)用程序之間的通信橋梁聯(lián)系起來(lái)。
驅(qū)動(dòng)程序的功能是將系統(tǒng)中的設(shè)備管理起來(lái),并向用戶空間提供一些接口,以便于用戶控制和使用系統(tǒng)中的設(shè)備。這其中,最重要的部分就是設(shè)備的注冊(cè)和管理。在 Linux 設(shè)備驅(qū)動(dòng)模型中,每個(gè)設(shè)備都有自己固定的屬性,例如它的名字、類型、硬件編號(hào)等。通過這些屬性,我們可以更方便快捷地管理系統(tǒng)中的設(shè)備,并調(diào)用其接口。
二. 設(shè)備驅(qū)動(dòng)模型的組織架構(gòu)
Linux 設(shè)備驅(qū)動(dòng)模型由多個(gè)組件構(gòu)成,在這些組件中,設(shè)備和驅(qū)動(dòng)程序分別被分配到不同的分層中進(jìn)行管理。下面是Linux 設(shè)備驅(qū)動(dòng)模型中的各個(gè)組件:
1.總線 (Bus)
總線是對(duì)設(shè)備和 CPU 之間的物理連接進(jìn)行抽象,以便于 Linux 內(nèi)核將其高效地管理??偩€是 Linux 設(shè)備驅(qū)動(dòng)模型的之一層組件,因?yàn)樗砹俗罨镜挠布M件。
Linux 內(nèi)核同時(shí)支持很多不同類型的總線,例如 PCI 總線、USB 總線、ACPI 總線、I2C 總線等,每種總線都有不同的特征和屬性。在 Linux 內(nèi)核中,總線是通過一個(gè)名為 bus_type 的結(jié)構(gòu)體來(lái)描述的。
2.設(shè)備 (Device)
設(shè)備是總線上附加的實(shí)體,它代表了一個(gè)特定類型的硬件實(shí)現(xiàn)。在 Linux 設(shè)備驅(qū)動(dòng)模型中,設(shè)備是第二層組件。每個(gè)設(shè)備都包括一個(gè)設(shè)備 ID(也稱為硬件 ID)和一個(gè)設(shè)備節(jié)點(diǎn)
3.驅(qū)動(dòng)程序 (Driver)
驅(qū)動(dòng)程序也是 Linux 設(shè)備驅(qū)動(dòng)模型中的重要組件,它負(fù)責(zé)把設(shè)備和應(yīng)用程序之間的通信橋梁聯(lián)系起來(lái)。驅(qū)動(dòng)程序是設(shè)備的第三層組件,在 Linux 內(nèi)核中,它由一個(gè)名為次設(shè)備對(duì)象 (sub-device) 的結(jié)構(gòu)體來(lái)表示。
驅(qū)動(dòng)程序的功能很多,包括初始化設(shè)備、分配 I/O 內(nèi)存空間、處理中斷、提供訪問接口等。這其中,其中最重要的是設(shè)備的注冊(cè)和管理,我們可以采用 sysfs 接口來(lái)操作設(shè)備的屬性,采用 device driver 接口進(jìn)行驅(qū)動(dòng)程序的編寫和注冊(cè)。
4.總線驅(qū)動(dòng) (Bus Driver)
總線驅(qū)動(dòng)是總線和設(shè)備之間的中間件,它將總線和設(shè)備的驅(qū)動(dòng)程序連接起來(lái),以便于更好地管理系統(tǒng)中的總線和設(shè)備對(duì)象。在 Linux 設(shè)備驅(qū)動(dòng)模型中,總線驅(qū)動(dòng)作為一個(gè)獨(dú)立的組件存在,其主要功能是通過總線接口與設(shè)備驅(qū)動(dòng)程序進(jìn)行通信??偩€驅(qū)動(dòng)是通過一個(gè)名為 bus_driver 的結(jié)構(gòu)體來(lái)描述的。
Linux 設(shè)備驅(qū)動(dòng)模型是一個(gè)非常復(fù)雜的結(jié)構(gòu),它由多個(gè)部件組合而成。每個(gè)部件都有自己特定的功能,并與其他部件相互關(guān)聯(lián),共同構(gòu)建一個(gè)健全的設(shè)備驅(qū)動(dòng)模型。
三. 設(shè)備驅(qū)動(dòng)模型的 API 接口
Linux 設(shè)備驅(qū)動(dòng)模型提供了許多 API 接口,我們可以利用這些接口來(lái)操作和管理系統(tǒng)中的各種設(shè)備和驅(qū)動(dòng)程序。以下是一些常用的 API 接口:
1.設(shè)備驅(qū)動(dòng)程序接口
設(shè)備驅(qū)動(dòng)程序接口指的是與設(shè)備驅(qū)動(dòng)程序相關(guān)的 API 接口,主要包括 “注冊(cè)驅(qū)動(dòng)程序”、”注銷驅(qū)動(dòng)程序”、“內(nèi)存分配接口”、“掛起接口”、“中斷處理接口”、“設(shè)備屬性操作接口等。
在 Linux 設(shè)備驅(qū)動(dòng)模型中,驅(qū)動(dòng)程序注冊(cè)是一個(gè)非常重要的過程。它幫助我們把設(shè)備的驅(qū)動(dòng)程序注冊(cè)到 Linux 內(nèi)核中去,以便系統(tǒng)可以識(shí)別、管理設(shè)備。注冊(cè)驅(qū)動(dòng)程序的過程可以調(diào)用 register_chrdev() 函數(shù)來(lái)實(shí)現(xiàn)。
2.設(shè)備節(jié)點(diǎn)接口
設(shè)備節(jié)點(diǎn)接口是通過 sysfs 接口在設(shè)備樹中創(chuàng)建設(shè)備節(jié)點(diǎn)的接口。它幫助我們更方便地操作設(shè)備屬性和系統(tǒng)信息,并提供了一種標(biāo)準(zhǔn)化的數(shù)據(jù)交換格式。
在設(shè)備節(jié)點(diǎn)接口中,我們可以使用 sysfs 接口來(lái)操作設(shè)備節(jié)點(diǎn)的屬性,例如寫入和讀取設(shè)備屬性、設(shè)定設(shè)備屬性等。
3.總線驅(qū)動(dòng)程序接口
總線驅(qū)動(dòng)程序是與總線驅(qū)動(dòng)相關(guān)的 API 接口,它可以幫助我們更好地管理系統(tǒng)中的總線和設(shè)備對(duì)象。
總線驅(qū)動(dòng)程序接口提供了一些函數(shù),例如總線驅(qū)動(dòng)程序注冊(cè)函數(shù)、設(shè)備驅(qū)動(dòng)程序綁定函數(shù)、設(shè)備驅(qū)動(dòng)程序解綁函數(shù)等,這些函數(shù)可以在驅(qū)動(dòng)程序的編寫和注冊(cè)中加以使用,以幫助我們更好地管理系統(tǒng)設(shè)備。
本文主要介紹了 Linux 設(shè)備驅(qū)動(dòng)模型的原理、組織架構(gòu)和 API 接口。通過這些知識(shí),我們已經(jīng)可以更加深入地了解 Linux 設(shè)備驅(qū)動(dòng)模型,并在實(shí)際中更好地操作和管理系統(tǒng)中的各種設(shè)備和驅(qū)動(dòng)程序。希望這篇文章對(duì)大家有所幫助。
相關(guān)問題拓展閱讀:
- linux的內(nèi)核模塊都在哪里放著啊
- Linux 磁盤IO
linux的內(nèi)核模塊都在哪里放著啊
一個(gè)完整的Linux內(nèi)核一般由5部分組成,它們分別是內(nèi)存管理、進(jìn)程管理、進(jìn)程間通信、虛擬文件系統(tǒng)和網(wǎng)絡(luò)接口。1、內(nèi)存管理內(nèi)存管理主要完成的是如何合理有效地管理整個(gè)系統(tǒng)的物理內(nèi)存,同時(shí)快速響應(yīng)內(nèi)核各個(gè)子系統(tǒng)對(duì)內(nèi)存分配的請(qǐng)求。Linux內(nèi)存管理支持虛擬內(nèi)存,而多余出的這部分內(nèi)存就是通過磁盤申請(qǐng)得到的,平時(shí)系統(tǒng)只把當(dāng)前運(yùn)行的程序塊保留在內(nèi)存中,其他程序塊則保留在磁盤中。薯返在內(nèi)存緊缺時(shí),內(nèi)存管理負(fù)責(zé)在磁盤和內(nèi)存間交換程序塊。2、進(jìn)程管理進(jìn)程管理主要盯手舉控制系統(tǒng)進(jìn)程對(duì)CPU的訪問。當(dāng)需要某個(gè)進(jìn)程運(yùn)行時(shí),由進(jìn)程調(diào)度器根據(jù)基于優(yōu)先級(jí)的調(diào)度算法啟動(dòng)新的進(jìn)程。:Linux支持多任務(wù)運(yùn)行,那么如何在一個(gè)單CPU上支持多任務(wù)呢?這個(gè)工作就是由進(jìn)程調(diào)度管理來(lái)凱碧實(shí)現(xiàn)的。在系統(tǒng)運(yùn)行時(shí),每個(gè)進(jìn)程都會(huì)分得一定的時(shí)間片,然后進(jìn)程調(diào)度器根據(jù)時(shí)間片的不同,選擇每個(gè)進(jìn)程依次運(yùn)行,例如當(dāng)某個(gè)進(jìn)程的時(shí)間片用完后,調(diào)度器會(huì)選擇一個(gè)新的進(jìn)程繼續(xù)運(yùn)行。由于切換的時(shí)間和頻率都非常的快,由此用戶感覺是多個(gè)程序在同時(shí)運(yùn)行,而實(shí)際上,CPU在同一時(shí)間內(nèi)只有一個(gè)進(jìn)程在運(yùn)行,這一切都是進(jìn)程調(diào)度管理的結(jié)果。3、進(jìn)程間通信進(jìn)程間通信主要用于控制不同進(jìn)程之間在用戶空間的同步、數(shù)據(jù)共享和交換。由于不用的用戶進(jìn)程擁有不同的進(jìn)程空間,因此進(jìn)程間的通信要借助于內(nèi)核的中轉(zhuǎn)來(lái)實(shí)現(xiàn)。一般情況下,當(dāng)一個(gè)進(jìn)程等待硬件操作完成時(shí),會(huì)被掛起。當(dāng)硬件操作完成,進(jìn)程被恢復(fù)執(zhí)行,而協(xié)調(diào)這個(gè)過程的就是進(jìn)程間的通信機(jī)制。4、虛擬文件系統(tǒng)Linux內(nèi)核中的虛擬文件系統(tǒng)用一個(gè)通用的文件模型表示了各種不同的文件系統(tǒng),這個(gè)文件模型屏蔽了很多具體文件系統(tǒng)的差異,使Linux內(nèi)核支持很多不同的文件系統(tǒng),這個(gè)文件系統(tǒng)可以分為邏輯文件系統(tǒng)和設(shè)備驅(qū)動(dòng)程序:邏輯文件系統(tǒng)指Linux所支持的文件系統(tǒng),例如ext2、ext3和fat等;設(shè)備驅(qū)動(dòng)程序指為每一種硬件控制器所編寫的設(shè)備驅(qū)動(dòng)程序模塊。5、網(wǎng)絡(luò)接口網(wǎng)絡(luò)接口提供了對(duì)各種網(wǎng)絡(luò)標(biāo)準(zhǔn)的實(shí)現(xiàn)和各種網(wǎng)絡(luò)硬件的支持。網(wǎng)絡(luò)接口一般分為網(wǎng)絡(luò)協(xié)議和網(wǎng)絡(luò)驅(qū)動(dòng)程序。網(wǎng)絡(luò)協(xié)議部分負(fù)責(zé)實(shí)現(xiàn)每一種可能的網(wǎng)絡(luò)傳輸協(xié)議。網(wǎng)絡(luò)設(shè)備驅(qū)動(dòng)程序則主要負(fù)責(zé)與硬件設(shè)備進(jìn)行通信,每一種可能的網(wǎng)絡(luò)硬件設(shè)備都有相應(yīng)的設(shè)備驅(qū)動(dòng)程序。
Linux 磁盤IO
磁盤結(jié)構(gòu)與數(shù)據(jù)存儲(chǔ)方式, 數(shù)據(jù)是如何存儲(chǔ)的,又通過怎樣的方式被訪問?
機(jī)械硬盤主要由磁盤盤片、磁頭、主軸與傳動(dòng)軸等組成;數(shù)據(jù)就存放在磁盤盤片中
現(xiàn)代硬盤尋道都是采用CHS( Cylinder Head Sector )的方式,硬盤讀取數(shù)據(jù)時(shí),讀寫磁頭沿徑向移動(dòng),移到要讀取的扇區(qū)所在磁道的上方,這段時(shí)間稱為
尋道時(shí)間(seek time)
。
因讀寫磁頭的起始位置與目標(biāo)位置之間的距離不同,尋道時(shí)間也不同
。磁頭到達(dá)指定磁道后,然后通過盤片的旋轉(zhuǎn),使得要讀取的扇區(qū)轉(zhuǎn)到讀寫磁頭的下方,這段時(shí)間稱為
旋轉(zhuǎn)延遲時(shí)間(rotational latencytime)
。然后再讀寫數(shù)據(jù),讀手租寫數(shù)據(jù)也需要時(shí)間,這段時(shí)間稱為
傳輸時(shí)間(transfer time)
。
固態(tài)硬盤主要由主控芯片、閃存顆粒與緩存組成;數(shù)據(jù)就存放在閃存芯片中
通過主控芯片進(jìn)行尋址, 因?yàn)楫吅谜资请娦盘?hào)方式, 沒有任何物理結(jié)構(gòu), 所以尋址速度非??烨遗c數(shù)據(jù)存儲(chǔ)位置無(wú)關(guān)
如何查看系統(tǒng)IO狀態(tài)
查看磁盤空間
調(diào)用 open , fwrite 時(shí)到底發(fā)生了什么?
在一個(gè)IO過程中,以下5個(gè)API/系統(tǒng)調(diào)用是必不可少的
Create 函數(shù)用來(lái)打開一個(gè)文件,如果該文件不存在,那么需要在磁盤上創(chuàng)建該文件
Open 函數(shù)用于打開一個(gè)指定的文件。如果在 Open 函數(shù)中指定 O_CREATE 標(biāo)記,那么 Open 函數(shù)同樣可以實(shí)現(xiàn) Create 函數(shù)的功能
Clos e函數(shù)用于釋放文件句柄
Write 和 Read 函數(shù)用于實(shí)現(xiàn)文件的讀寫過程
O_SYNC (先寫緩存, 但是需要實(shí)際落襪粗盤之后才返回, 如果接下來(lái)有讀請(qǐng)求, 可以從內(nèi)存讀 ), write-through
O_DSYNC (D=data, 類似O_SYNC, 但是只同步數(shù)據(jù), 不同步元數(shù)據(jù))
O_DIRECT (直接寫盤, 不經(jīng)過緩存)
O_ASYNC (異步IO, 使用信號(hào)機(jī)制實(shí)現(xiàn), 不推薦, 直接用aio_xxx)
O_NOATIME (讀取的時(shí)候不更新文件 atime(access time))
sync() 全局緩存寫回磁盤
fsync() 特定fd的sync()
fdatasync() 只刷數(shù)據(jù), 不同步元數(shù)據(jù)
mount noatime(全局不記錄atime), re方式(只讀), sync(同步方式)
一個(gè)IO的傳奇一生 這里有一篇非常好的資料,講述了整個(gè)IO過程;
下面簡(jiǎn)單記錄下自己的理解的一次常見的Linux IO過程, 想了解更詳細(xì)及相關(guān)源碼,非常推薦閱讀上面的原文
Linux IO體系結(jié)構(gòu)
Superblock
超級(jí)描述了整個(gè)文件系統(tǒng)的信息。為了保證可靠性,可以在每個(gè)塊組中對(duì)superblock進(jìn)行備份。為了避免superblock冗余過多,可以采用稀疏存儲(chǔ)的方式,即在若干個(gè)塊組中對(duì)superblock進(jìn)行保存,而不需要在所有的塊組中都進(jìn)行備份
GDT 組描述符表
組描述符表對(duì)整個(gè)組內(nèi)的數(shù)據(jù)布局進(jìn)行了描述。例如,數(shù)據(jù)塊位圖的起始地址是多少?inode位圖的起始地址是多少?inode表的起始地址是多少?塊組中還有多少空閑塊資源等。組描述符表在superblock的后面
數(shù)據(jù)塊位圖
數(shù)據(jù)塊位圖描述了塊組內(nèi)數(shù)據(jù)塊的使用情況。如果該數(shù)據(jù)塊已經(jīng)被某個(gè)文件使用,那么位圖中的對(duì)應(yīng)位會(huì)被置1,否則該位為0
Inode位圖
Inode位圖描述了塊組內(nèi)inode資源使用情況。如果一個(gè)inode資源已經(jīng)使用,那么對(duì)應(yīng)位會(huì)被置1
Inode表
(即inode資源)和數(shù)據(jù)塊。這兩塊占據(jù)了塊組內(nèi)的絕大部分空間,特別是數(shù)據(jù)塊資源
一個(gè)文件是由inode進(jìn)行描述的。一個(gè)文件占用的數(shù)據(jù)塊block是通過inode管理起來(lái)的
。在inode結(jié)構(gòu)中保存了直接塊指針、一級(jí)間接塊指針、二級(jí)間接塊指針和三級(jí)間接塊指針。對(duì)于一個(gè)小文件,直接可以采用直接塊指針實(shí)現(xiàn)對(duì)文件塊的訪問;對(duì)于一個(gè)大文件,需要采用間接塊指針實(shí)現(xiàn)對(duì)文件塊的訪問
最簡(jiǎn)單的調(diào)度器。它本質(zhì)上就是一個(gè)鏈表實(shí)現(xiàn)的
fifo
隊(duì)列,并對(duì)請(qǐng)求進(jìn)行簡(jiǎn)單的
合并
處理。
調(diào)度器本身并沒有提供任何可以配置的參數(shù)
讀寫請(qǐng)求被分成了兩個(gè)隊(duì)列, 一個(gè)用訪問地址作為索引,一個(gè)用進(jìn)入時(shí)間作為索引,并且采用兩種方式將這些request管理起來(lái);
在請(qǐng)求處理的過程中,deadline算法會(huì)優(yōu)先處理那些訪問地址臨近的請(qǐng)求,這樣可以更大程度的減少磁盤抖動(dòng)的可能性。
只有在有些request即將被餓死的時(shí)候,或者沒有辦法進(jìn)行磁盤順序化操作的時(shí)候,deadline才會(huì)放棄地址優(yōu)先策略,轉(zhuǎn)而處理那些即將被餓死的request
deadline算法可調(diào)整參數(shù)
read_expire
: 讀請(qǐng)求的超時(shí)時(shí)間設(shè)置(ms)。當(dāng)一個(gè)讀請(qǐng)求入隊(duì)deadline的時(shí)候,其過期時(shí)間將被設(shè)置為當(dāng)前時(shí)間+read_expire,并放倒fifo_list中進(jìn)行排序
write_expire
:寫請(qǐng)求的超時(shí)時(shí)間設(shè)置(ms)
fifo_batch
:在順序(sort_list)請(qǐng)求進(jìn)行處理的時(shí)候,deadline將以batch為單位進(jìn)行處理。每一個(gè)batch處理的請(qǐng)求個(gè)數(shù)為這個(gè)參數(shù)所限制的個(gè)數(shù)。在一個(gè)batch處理的過程中,不會(huì)產(chǎn)生是否超時(shí)的檢查,也就不會(huì)產(chǎn)生額外的磁盤尋道時(shí)間。這個(gè)參數(shù)可以用來(lái)平衡順序處理和饑餓時(shí)間的矛盾,當(dāng)饑餓時(shí)間需要盡可能的符合預(yù)期的時(shí)候,我們可以調(diào)小這個(gè)值,以便盡可能多的檢查是否有饑餓產(chǎn)生并及時(shí)處理。增大這個(gè)值當(dāng)然也會(huì)增大吞吐量,但是會(huì)導(dǎo)致處理饑餓請(qǐng)求的延時(shí)變長(zhǎng)
writes_starved
:這個(gè)值是在上述deadline出隊(duì)處理之一步時(shí)做檢查用的。用來(lái)判斷當(dāng)讀隊(duì)列不為空時(shí),寫隊(duì)列的饑餓程度是否足夠高,以時(shí)deadline放棄讀請(qǐng)求的處理而處理寫請(qǐng)求。當(dāng)檢查存在有寫請(qǐng)求的時(shí)候,deadline并不會(huì)立即對(duì)寫請(qǐng)求進(jìn)行處理,而是給相關(guān)數(shù)據(jù)結(jié)構(gòu)中的starved進(jìn)行累計(jì),如果這是之一次檢查到有寫請(qǐng)求進(jìn)行處理,那么這個(gè)計(jì)數(shù)就為1。如果此時(shí)writes_starved值為2,則我們認(rèn)為此時(shí)饑餓程度還不足夠高,所以繼續(xù)處理讀請(qǐng)求。只有當(dāng)starved >= writes_starved的時(shí)候,deadline才回去處理寫請(qǐng)求??梢哉J(rèn)為這個(gè)值是用來(lái)平衡deadline對(duì)讀寫請(qǐng)求處理優(yōu)先級(jí)狀態(tài)的,這個(gè)值越大,則寫請(qǐng)求越被滯后處理,越小,寫請(qǐng)求就越可以獲得趨近于讀請(qǐng)求的優(yōu)先級(jí)
front_merges
:當(dāng)一個(gè)新請(qǐng)求進(jìn)入隊(duì)列的時(shí)候,如果其請(qǐng)求的扇區(qū)距離當(dāng)前扇區(qū)很近,那么它就是可以被合并處理的。而這個(gè)合并可能有兩種情況,一個(gè)是向當(dāng)前位置后合并,另一種是向前合并。在某些場(chǎng)景下,向前合并是不必要的,那么我們就可以通過這個(gè)參數(shù)關(guān)閉向前合并。默認(rèn)deadline支持向前合并,設(shè)置為0關(guān)閉
在調(diào)度一個(gè)request時(shí),首先需要選擇一個(gè)一個(gè)合適的cfq_group。Cfq調(diào)度器會(huì)為每個(gè)cfq_group分配一個(gè)時(shí)間片,當(dāng)這個(gè)時(shí)間片耗盡之后,會(huì)選擇下一個(gè)cfq_group。每個(gè)cfq_group都會(huì)分配一個(gè)vdisktime,并且通過該值采用紅黑樹對(duì)cfq_group進(jìn)行排序。在調(diào)度的過程中,每次都會(huì)選擇一個(gè)vdisktime最小的cfq_group進(jìn)行處理。
一個(gè)cfq_group管理了7棵service tree,每棵service tree管理了需要調(diào)度處理的對(duì)象cfq_queue。因此,一旦cfq_group被選定之后,需要選擇一棵service tree進(jìn)行處理。這7棵service tree被分成了三大類,分別為RT、BE和IDLE。這三大類service tree的調(diào)度是按照優(yōu)先級(jí)展開的
通過優(yōu)先級(jí)可以很容易的選定一類Service tree。當(dāng)一類service tree被選定之后,采用service time的方式選定一個(gè)合適的cfq_queue。每個(gè)Service tree是一棵紅黑樹,這些紅黑樹是按照service time進(jìn)行檢索的,每個(gè)cfq_queue都會(huì)維護(hù)自己的service time。分析到這里,我們知道,cfq算法通過每個(gè)cfq_group的vdisktime值來(lái)選定一個(gè)cfq_group進(jìn)行服務(wù),在處理cfq_group的過程通過優(yōu)先級(jí)選擇一個(gè)最需要服務(wù)的service tree。通過該Service tree得到最需要服務(wù)的cfq_queue。該過程在 cfq_select_queue 函數(shù)中實(shí)現(xiàn)
一個(gè)cfq_queue被選定之后,后面的過程和deadline算法有點(diǎn)類似。在選擇request的時(shí)候需要考慮每個(gè)request的延遲等待時(shí)間,選擇那種等待時(shí)間最長(zhǎng)的request進(jìn)行處理。但是,考慮到磁盤抖動(dòng)的問題,cfq在處理的時(shí)候也會(huì)進(jìn)行順序批量處理,即將那些在磁盤上連續(xù)的request批量處理掉
cfq調(diào)度算法的參數(shù)
back_seek_max
:磁頭可以向后尋址的更大范圍,默認(rèn)值為16M
back_seek_penalty
:向后尋址的懲罰系數(shù)。這個(gè)值是跟向前尋址進(jìn)行比較的
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í),就是超過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ù)跟上面的類似,區(qū)別是用來(lái)設(shè)置同步請(qǐng)求的超時(shí)時(shí)間
slice_idle
:參數(shù)設(shè)置了一個(gè)等待時(shí)間。這讓cfq在切換cfq_queue或service tree的時(shí)候等待一段時(shí)間,目的是提高機(jī)械硬盤的吞吐量。一般情況下,來(lái)自同一個(gè)cfq_queue或者service tree的IO請(qǐng)求的尋址局部性更好,所以這樣可以減少磁盤的尋址次數(shù)。這個(gè)值在機(jī)械硬盤上默認(rèn)為非零。當(dāng)然在固態(tài)硬盤或者硬RAID設(shè)備上設(shè)置這個(gè)值為非零會(huì)降低存儲(chǔ)的效率,因?yàn)楣虘B(tài)硬盤沒有磁頭尋址這個(gè)概念,所以在這樣的設(shè)備上應(yīng)該設(shè)置為0,關(guān)閉此功能
group_idle
:這個(gè)參數(shù)也跟上一個(gè)參數(shù)類似,區(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)行,以防止上述問題產(chǎn)生
low_latency
:這個(gè)是用來(lái)開啟或關(guān)閉cfq的低延時(shí)(low latency)模式的開關(guān)。當(dāng)這個(gè)開關(guān)打開時(shí),cfq將會(huì)根據(jù)target_latency的參數(shù)設(shè)置來(lái)對(duì)每一個(gè)進(jìn)程的分片時(shí)間(slice time)進(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è)開關(guān)默認(rèn)是打開的
target_latency
:當(dāng)low_latency的值為開啟狀態(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ì)列處理事件周期中,超過這個(gè)數(shù)字的IO請(qǐng)求將不會(huì)被處理。這個(gè)參數(shù)只對(duì)同步的請(qǐng)求有效
slice_sync
:當(dāng)一個(gè)cfq_queue隊(duì)列被調(diào)度處理時(shí),它可以被分配的處理總時(shí)間是通過這個(gè)值來(lái)作為一個(gè)計(jì)算參數(shù)指定的。公式為: time_slice = slice_sync + (slice_sync/5 * (4 – prio)) 這個(gè)參數(shù)對(duì)同步請(qǐng)求有效
slice_async
:這個(gè)值跟上一個(gè)類似,區(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)
通常在Linux上使用的IO接口是同步方式的,進(jìn)程調(diào)用 write / read 之后會(huì)阻塞陷入到內(nèi)核態(tài),直到本次IO過程完成之后,才能繼續(xù)執(zhí)行,下面介紹的異步IO則沒有這種限制,但是當(dāng)前Linux異步IO尚未成熟
目前Linux aio還處于較不成熟的階段,只能在 O_DIRECT 方式下才能使用(glibc_aio),也就是無(wú)法使用默認(rèn)的Page Cache機(jī)制
正常情況下,使用aio族接口的簡(jiǎn)要方式如下:
io_uring 是 2023 年 5 月發(fā)布的 Linux 5.1 加入的一個(gè)重大特性 —— Linux 下的全新的異步 I/O 支持,希望能徹底解決長(zhǎng)期以來(lái) Linux AIO 的各種不足
io_uring 實(shí)現(xiàn)異步 I/O 的方式其實(shí)是一個(gè)生產(chǎn)者-消費(fèi)者模型:
邏輯卷管理
RAID0
RAID1
RAID5(糾錯(cuò))
條帶化
Linux系統(tǒng)性能調(diào)整:IO過程
Linux的IO調(diào)度
一個(gè)IO的傳奇一生
理解inode
Linux 文件系統(tǒng)是怎么工作的?
Linux中Buffer cache性能問題一探究竟
Asynchronous I/O and event notification on linux
AIO 的新歸宿:io_uring
關(guān)于linux 設(shè)備驅(qū)動(dòng)模型的介紹到此就結(jié)束了,不知道你從中找到你需要的信息了嗎 ?如果你還想了解更多這方面的信息,記得收藏關(guān)注本站。
成都服務(wù)器租用選創(chuàng)新互聯(lián),先試用再開通。
創(chuàng)新互聯(lián)(www.cdcxhl.com)提供簡(jiǎn)單好用,價(jià)格厚道的香港/美國(guó)云服務(wù)器和獨(dú)立服務(wù)器。物理服務(wù)器托管租用:四川成都、綿陽(yáng)、重慶、貴陽(yáng)機(jī)房服務(wù)器托管租用。
文章題目:Linux設(shè)備驅(qū)動(dòng)模型原理解析 (linux 設(shè)備驅(qū)動(dòng)模型)
分享鏈接:http://m.5511xx.com/article/cdejeji.html


咨詢
建站咨詢
