若塊裝置驅動程式也按以下字元裝置驅動程式的簡單思想來寫:
1.硬碟
磁碟的讀寫其實非常快,慢在機械結構讀寫裝置的定位上面,從乙個「磁頭」的某「柱面」某「扇區」讀到資料後(步驟 r0),跳到另乙個「磁頭」的某「柱面」的某「扇區」去寫(步驟 w),接著再跳回原「磁頭」相同柱面的下乙個「扇區」去讀(步驟r1)。慢就慢在讀寫扇區的跳轉過程中。若按「字元裝置」中的「opne」 ,「read」, "write"方式,則總體效率在硬碟的讀寫上會非常低。
上面過程是「r0」->「w」->「r1」,這個步驟跳轉 2 次。
若優化這個步驟為:r0->r1->w。這個步驟跳轉 1 次。這樣效率會高些。
總結:先不執行而是放入佇列,優化後再執行(對硬碟有這種要求)。用「字元裝置驅動」程式那樣讀寫時就會在硬碟上跳來跳去,整體效率會非常低。所以有必要引入「優化過程」。就是讀寫先不執行,先放到某個「佇列」中去。(調整順序)
flash「塊」裡有乙個乙個的扇區。若按字元裝置方法讀寫,要先寫「扇區 0」和「扇區 1」。flash 要先擦除再寫,擦除是整塊整塊的進行的。
寫扇區 0 的過程:
①,要寫時,先把這整塊讀到乙個 buf 中。
②,然後修改 buf 中扇區 0 的資料。
③,這時再擦除整塊。
④,再把修改過扇區 0 的資料的 buf 燒寫到整塊。
寫扇區 1 的過程:
①,要寫時,先把這整塊讀到乙個 buf 中。
②,然後修改 buf 中扇區 1 的資料。
③,這時再擦除整塊。
④,再把修改過扇區 1 的資料的 buf 燒寫到整塊
則那麼要修改多個扇區時,會擦除燒寫多次。總體效率也會低。
優化:①,先不執行。
②,優化 - 合併後執行。
合併:合併後只需要一次。
a,讀出整塊到 buf 中。
b,在 buf 中修改扇區 0 和扇區 1。
c,擦除。
d,燒寫。
總結:塊裝置不能像字元裝置那樣提供讀寫函式。
①,先把讀寫放入佇列,先不執行。
②,優化後再執行。
應用程式讀寫乙個普通的檔案,最終要轉換成操作硬體,由塊裝置驅動來操作硬體。引入檔案系統把對普通檔案的讀寫轉換成對扇區的讀寫,有個通用的入口ll_rw_block(low level,底層讀寫塊)。讀寫請求會放入佇列優化後執行,ll_rw_block會把"讀寫"放入佇列,呼叫佇列的處理函式(優化/調順序/合併)。我們不關心檔案系統,關心塊裝置驅動程式。檔案系統就是檔案的組織格式,buffer.c位於fs的根目錄,是個通用的檔案。
分析ll_rw_block
void
ll_rw_block
(int rw,
int nr,
struct buffer_head *bhs)
//rw表示讀/寫,資料傳輸三要素:源、目的、長度放在buffer_head裡面,buffer_head這是個陣列,有nr個陣列項。
for(i =
0; i < nr; i++
);
用blk_init_queue(do_ramblock_request, &ramblock_lock)函式分配乙個佇列,blk_init_queue初始化函式裡提供了預設的構造請求的函式__make_request。
前面說把對檔案的讀寫轉換成塊裝置的讀寫,對這些扇區的讀寫會放到佇列裡面。把bh構造為bio,把bio放入佇列裡面,呼叫佇列裡面的構造請求的函式make_request_fn(q, bio),佇列裡面有個__make_request構造請求的函式,它有預設的函式。
當我們初始化佇列的時候,它給我們提供預設的構造請求函式__make_request,當它把請求放入佇列之後,以後會用到佇列裡的request_fn來處理,而request_fn是blk_init_queue函式中傳入的第乙個引數,所以最終會呼叫do_ramblock_request來處理那些請求。
struct request
static
struct block_device_operations ramblock_fops =
;//處理佇列函式,用記憶體模擬,讀寫用memcopy
static
void
do_ramblock_request
(request_queue_t * q)
else
end_request
(req,1)
;//1表示成功,0表示失敗}}
static
intramblock_init
(void
)static
void
ramblock_exit
(void
)module_init
(ramblock_init)
;module_exit
(ramblock_exit)
;module_license
("gpl"
);
雖然用記憶體模擬磁碟沒有磁頭、柱面、扇區這些概念,但為了用這個老工具fdisk分割槽工具,要假裝有這些東西。在ramblock_fops中設定.getgeo=ramblock_getgeo,獲得幾何屬性。
塊裝置框架:
寫塊裝置驅動程式,分配gendisk: alloc_disk結構體,設定分為兩部分。一部分設定佇列: request_queue_t提供讀寫能力,另外是設定gendisk其他資訊比如容量,然後註冊: add_disk就可以了。以後的操作不用操心,格式化或讀寫檔案由檔案系統這一層幫你把檔案的讀寫轉換成對扇區的讀寫。呼叫ll-rw-block,它會把讀寫放到佇列裡,會呼叫佇列裡的函式來處理,我們只要寫好處理佇列的函式do_ramblock_request。
裝置驅動 塊裝置驅動程式
塊裝置驅動程式提供對面向塊的裝置的訪問,這種裝置以隨機訪問的方式傳輸資料,並且資料總是具有固定大小的塊。典型的塊裝置是磁碟驅動器,也有其它型別的塊裝置。塊裝置和字元裝置有很大區別。比如塊裝置上可以掛載檔案系統,字元裝置不可以。這是隨機訪問帶來的優勢,因為檔案系統需要能按塊儲存資料,同時更需要能隨機讀...
Linux塊裝置驅動
塊裝置提供塊裝置提供裝置的訪問,裝置的訪問,可以隨機的以固定大小的塊傳輸資料,例如我們最為常見的磁碟裝置,當然塊裝置和字元裝置有較大差別,塊裝置有自己的驅動介面。簡單來說,核心決定乙個塊是固定的4096 位元組,當然該值可以隨著依賴檔案系統的變化而改變。塊裝置驅動採用register blkdev向...
塊裝置驅動 流程
環境 centos 虛擬機器 zyq promote disk cat makefile obj m ramhd.o ramhd objs ramhd mkreq.o kerneldir lib modules shell uname r build pwd shell pwd default ma...