zoukankan      html  css  js  c++  java
  • 编写简单的ramdisk(选择IO调度器)

    前言

      目前linux中包含anticipatorycfqdeadlinenoop4I/O调度器。2.6.18之前的linux默认使用anticipatory,而之后的默认使用cfq。我们在前面编写简单的ramdisk(有请求队列)中分配请求队列使用了blk_init_queue函数,该函数会默认该请求队列分配一个调度器,这里我们打算不使用该函数默认分配给请求队列的调度器,而是使用noop调度器。noop顾名思义,是一个基本上不干事的调度器。它基本不对请求进行什么附加的处理,仅仅假惺惺地告诉通用块设备层:我处理完了。但与吃空饷的公仆不同,noop的存在还是有不少进步意义的。至少我们现在就需要一个不要没事添乱的I/O调度器。

    选择一个指定的IO调度器

      可以用下面的函数来更换一个请求队列的调度器,该函数定义如下:

    1 int elevator_change(struct request_queue *, const char *)

      第一个参数是请求队列的指针,第二个参数是需要设定的I/O调度器名称。如果nameNULL,那么内核会首先尝试选择启动参数"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 {
     3         int ret;
     4         struct elevator_queue *elv_old;
     5 
     6         //分配一个请求队列
     7         simp_blkdev_queue = blk_init_queue(simp_blkdev_do_request, NULL);
     8         if(!simp_blkdev_queue) 
     9         {
    10             ret = -ENOMEM;
    11             goto blk_init_queue;
    12         }
    13         //更换IO调度器
    14         if (IS_ERR_VALUE(elevator_change(simp_blkdev_queue, "noop")))
    15             printk(KERN_WARNING "Switch elevator failed, using default
    ");
    16         
    17         //分配一个 gendisk 结构,有一个分区
    18         simp_blkdev_disk = alloc_disk(1);
    19         if(!simp_blkdev_disk) 
    20         {
    21             ret = -ENOMEM;
    22             goto err_alloc_disk;
    23         }
    24     
    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         //向内核注册块设备驱动
    34         add_disk(simp_blkdev_disk);
    35 
    36         return 0;
    37 
    38 err_alloc_disk:
    39         blk_cleanup_queue(simp_blkdev_queue);
    40 blk_init_queue:
    41         return 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 {
     3         int ret;
     4         struct elevator_queue *elv_old;
     5 
     6         //分配一个请求队列
     7         simp_blkdev_queue = blk_init_queue(simp_blkdev_do_request, NULL);
     8         if(!simp_blkdev_queue) 
     9         {
    10             ret = -ENOMEM;
    11             goto blk_init_queue;
    12         }
    13         
    14         elv_old = simp_blkdev_queue->elevator;
    15         simp_blkdev_queue->elevator = NULL;
    16         //更换IO调度器
    17         if (IS_ERR_VALUE(elevator_init(simp_blkdev_queue, "noop")))
    18             printk(KERN_WARNING "Switch elevator failed, using default
    ");
    19         else
    20             elevator_exit(elv_old);
    21         //分配一个 gendisk 结构,有一个分区
    22         simp_blkdev_disk = alloc_disk(1);
    23         if(!simp_blkdev_disk) 
    24         {
    25             ret = -ENOMEM;
    26             goto err_alloc_disk;
    27         }
    28     
    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         //向内核注册块设备驱动
    38         add_disk(simp_blkdev_disk);
    39 
    40         return 0;
    41 
    42 err_alloc_disk:
    43         blk_cleanup_queue(simp_blkdev_queue);
    44 blk_init_queue:
    45         return ret;
    46 }

     

     

     

  • 相关阅读:
    Binary Tree Maximum Path Sum
    ZigZag Conversion
    Longest Common Prefix
    Reverse Linked List II
    Populating Next Right Pointers in Each Node
    Populating Next Right Pointers in Each Node II
    Rotate List
    Path Sum II
    [Leetcode]-- Gray Code
    Subsets II
  • 原文地址:https://www.cnblogs.com/chengxuyuancc/p/3551806.html
Copyright © 2011-2022 走看看