目前linux
中包含anticipatory
、cfq
、deadline
和noop這4
個i/o
排程器。
2.6.18
之前的linux
預設使用
anticipatory
,而之後的預設使用
cfq。我們在前面
編寫簡單的ramdisk(有請求佇列)中分配請求佇列使用了blk_init_queue函式,該函式會預設該請求佇列分配乙個排程器,這裡我們打算不使用該函式預設分配給請求佇列的排程器,而是使用noop排程器。noop
顧名思義,是乙個基本上不幹事的排程器。它基本不對請求進行什麼附加的處理,僅僅假惺惺地告訴通用塊裝置層:我處理完了。但與吃空餉的公僕不同,
noop
的存在還是有不少進步意義的。至少我們現在就需要乙個不要沒事添亂的
i/o排程器。
可以用下面的函式來更換乙個請求佇列的排程器,該函式定義如下:
1int elevator_change(struct request_queue *, const
char *)
第乙個引數是請求佇列的指標,第二個引數是需要設定的i/o
排程器名稱。如果
name
為null
,那麼核心會首先嘗試選擇啟動引數
"elevator="
中指定的排程器,不成功的話就去選擇編譯核心時指定的預設排程器,如果運氣太背還是不成功,就去選擇
"noop"
排程器。
對於我們的**,就是在simp_blkdev_queue = blk_init_queue(simp_blkdev_do_request, null)
後面加上elevator_change(simp_blkdev_queue, "noop");所以我們的**應該是(
顏色為紅色的**是選擇排程器**
):
1static
int __init simp_blkdev_init(void)2
13//
更換io排程器
14if (is_err_value(elevator_change(simp_blkdev_queue, "noop")))
15printk(kern_warning "switch elevator failed, using default\n");
1617
//分配乙個 gendisk 結構,有乙個分割槽
18 simp_blkdev_disk = alloc_disk(1
);19
if(!simp_blkdev_disk)
2024
25//
填充 gendisk 主要結構成員
26 strcpy(simp_blkdev_disk->disk_name, simp_blkdev_diskname);
27 simp_blkdev_disk->major =simp_blkdev_devicemajor;
28 simp_blkdev_disk->first_minor = 0
;29 simp_blkdev_disk->fops = &simp_blkdev_fops;
30 simp_blkdev_disk->queue =simp_blkdev_queue;
31 set_capacity(simp_blkdev_disk, simp_blkdev_bytes >> 9
);32
33//
向核心註冊塊裝置驅動
34add_disk(simp_blkdev_disk);
3536
return0;
3738
err_alloc_disk:
39blk_cleanup_queue(simp_blkdev_queue);
40blk_init_queue:
41return
ret;
42 }
如果要用函式elevator_init
來設定排程器,就必須先儲存原來blk_init_queue()幫我們申請的預設排程器,然後設定佇列中的指向排程器的elevator指標為
null(注意:設定指標為null是必須的,要不然函式elevator_init會不做任何事情直接返回)
,最後才是呼叫
elevator_init(simp_blkdev_queue, "noop")來設定,如果設定成功則呼叫
elevator_exit
來釋放原來的排程器。具體**如下(顏色為紅色的**是選擇排程器**):
1static
int __init simp_blkdev_init(void)2
1314
elv_old = simp_blkdev_queue->elevator;
15simp_blkdev_queue->elevator = null;
16//
更換io排程器
17if (is_err_value(elevator_init(simp_blkdev_queue, "noop")))
18printk(kern_warning "switch elevator failed, using default\n");
19else
20elevator_exit(elv_old);
21//
分配乙個 gendisk 結構,有乙個分割槽
22 simp_blkdev_disk = alloc_disk(1
);23
if(!simp_blkdev_disk)
2428
29//
填充 gendisk 主要結構成員
30 strcpy(simp_blkdev_disk->disk_name, simp_blkdev_diskname);
31 simp_blkdev_disk->major =simp_blkdev_devicemajor;
32 simp_blkdev_disk->first_minor = 0
;33 simp_blkdev_disk->fops = &simp_blkdev_fops;
34 simp_blkdev_disk->queue =simp_blkdev_queue;
35 set_capacity(simp_blkdev_disk, simp_blkdev_bytes >> 9
);36
37//
向核心註冊塊裝置驅動
38add_disk(simp_blkdev_disk);
3940
return0;
4142
err_alloc_disk:
43blk_cleanup_queue(simp_blkdev_queue);
44blk_init_queue:
45return
ret;
46 }
編寫簡單的ramdisk(有請求佇列)
前面用無請求佇列實現的ramdisk 的驅動程式雖然申請了請求佇列,但實際上沒用上,因為 ramdisk 不像實際的磁碟訪問速度慢需要快取,ramdisk 之間使用記憶體空間,所以就沒用請求佇列了。本文將介紹使用請求佇列的 ramdisk 驅動,雖然對於 ramdisk 使用請求佇列用處不大,但對於...
編寫簡單的makefile
假如有乙個上百個檔案的 構成的專案,如果只是對其中乙個或少數幾個檔案進行了修改,若用gcc編譯工具就不得不把整個專案裡的檔案重新編譯一遍。編譯過程分為編譯 彙編鏈結等階段。其中,編譯階段僅檢查語法錯誤以及函式與變數的宣告是否正確,在鏈結階段則主要完成函式鏈結和全域性變數的鏈結。因此,沒有改動的源 根...
簡單的makefile編寫
cc gcc cflags wall i home coc target sysroots corei7 64 poky linux usr include libxml2 ldflags l home coc target sysroots corei7 64 poky linux usr lib...