ll_rw_block是檔案系統對下訪問實際的塊裝置驅動的介面,應用程式對實際檔案(非裝置檔案)的操作,最終都是
通過檔案系統來調用ll_rw_block來操作實際的存放裝置的。
當然ll_rw_block的實際作用遠非一個介面那麼簡單,他裡面對維護了一個讀寫請求隊列,並且對隊列裡讀寫請求進
行了最佳化,比如,對機械硬碟來說,使用了電梯演算法,對隊列裡的讀寫請求進行最佳化,排序,合并等操作,提高了
訪問硬碟的效率。最佳化後,最後調用實際的塊裝置驅動程式來操作真正的存放裝置。
下面,以bbb的TI官方linux源碼(sdk6)來大概將ll_rw_block的流程寫一下,以免忘記。
void ll_rw_block(int rw, int nr, struct buffer_head *bhs[]) // fs/buffer.c
{
//rw為讀寫標誌,nr為bhs數組的長度, bhs為實際要對寫資料的資訊數組,源,目的,長度
for (i = 0; i < nr; i++) {
struct buffer_head *bh = bhs[i];
if (rw == WRITE) {
submit_bh(WRITE, bh); //提交寫請求
} else {
submit_bh(rw, bh); //提交讀請求
}
}
}
int submit_bh(int rw, struct buffer_head * bh) // fs/buffer.c
{
struct bio *bio;
//這裡省略了一系列的使用bh來構造bio的代碼,最終提交bio
bio_get(bio);
submit_bio(rw, bio); //提交bio
}
void submit_bio(int rw, struct bio *bio) //block/blk-core.c
{
generic_make_request(bio); //使用bio來構造請求
}
void generic_make_request(struct bio *bio) //block/blk-core.c
{
struct request_queue *q = bdev_get_queue(bio->bi_bdev); //獲得請求隊列
q->make_request_fn(q, bio); //調用請求隊列的make_request_fn
}
make_request_fn函數的定義如下:
void blk_queue_bio(struct request_queue *q, struct bio *bio) //block/blk-core.c
{
el_ret = elv_merge(q, &req, bio); //調用電梯演算法對讀寫操作進行最佳化處理
__blk_run_queue(q); //看下面
}
void __blk_run_queue(struct request_queue *q) //block/blk-core.c
{
q->request_fn(q); //這裡最終調用請求隊列的request_fn函數進行真正的磁碟操作
}