• 编写简单的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 }

     

     

     

  • 相关阅读:
    my sql Group_concat函数
    [Effective JavaScript 笔记]第43条:使用Object的直接实例构造轻量级的字典
    [Effective JavaScript 笔记]第4章:对象和原型--个人总结
    [Effective JavaScript 笔记]第42条:避免使用轻率的猴子补丁
    [Effective JavaScript 笔记]第41条:将原型视为实现细节
    [Effective JavaScript 笔记]第40条:避免继承标准类
    [Effective JavaScript 笔记]第39条:不要重用父类的属性名
    [Effective JavaScript 笔记]第38条:在子类的构造函数中调用父类的构造函数
    [Effective JavaScript 笔记]第37条:认识到this变量的隐式绑定问题
    [Effective JavaScript 笔记]第36条:只将实例状态存储在实例对象中
  • 原文地址:https://www.cnblogs.com/chengxuyuancc/p/3551806.html
Copyright © 2020-2023  润新知