編寫簡單的ramdisk(選擇IO排程器)

2022-07-09 21:30:22 字數 3589 閱讀 3701

目前linux

中包含anticipatory

、cfq

、deadline

和noop這4

個i/o

排程器。

2.6.18

之前的linux

預設使用

anticipatory

,而之後的預設使用

cfq。我們在前面

編寫簡單的ramdisk(有請求佇列)中分配請求佇列使用了blk_init_queue函式,該函式會預設該請求佇列分配乙個排程器,這裡我們打算不使用該函式預設分配給請求佇列的排程器,而是使用noop排程器。noop

顧名思義,是乙個基本上不幹事的排程器。它基本不對請求進行什麼附加的處理,僅僅假惺惺地告訴通用塊裝置層:我處理完了。但與吃空餉的公僕不同,

noop

的存在還是有不少進步意義的。至少我們現在就需要乙個不要沒事添亂的

i/o排程器。

可以用下面的函式來更換乙個請求佇列的排程器,該函式定義如下:

1

int 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");所以我們的**應該是(

顏色為紅色的**是選擇排程器**

):

1

static

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

來釋放原來的排程器。具體**如下(顏色為紅色的**是選擇排程器**):

1

static

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...