前言

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

选择一个指定的IO调度器

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

 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");所以我们的代码应该是(颜色为红色的代码是选择调度器代码):

 static int __init simp_blkdev_init(void)
{
int ret;
struct elevator_queue *elv_old; //分配一个请求队列
simp_blkdev_queue = blk_init_queue(simp_blkdev_do_request, NULL);
if(!simp_blkdev_queue)
{
ret = -ENOMEM;
goto blk_init_queue;
}
//更换IO调度器
if (IS_ERR_VALUE(elevator_change(simp_blkdev_queue, "noop")))
printk(KERN_WARNING "Switch elevator failed, using default\n"); //分配一个 gendisk 结构,有一个分区
simp_blkdev_disk = alloc_disk();
if(!simp_blkdev_disk)
{
ret = -ENOMEM;
goto err_alloc_disk;
} //填充 gendisk 主要结构成员
strcpy(simp_blkdev_disk->disk_name, SIMP_BLKDEV_DISKNAME);
simp_blkdev_disk->major = SIMP_BLKDEV_DEVICEMAJOR;
simp_blkdev_disk->first_minor = ;
simp_blkdev_disk->fops = &simp_blkdev_fops;
simp_blkdev_disk->queue = simp_blkdev_queue;
set_capacity(simp_blkdev_disk, SIMP_BLKDEV_BYTES >> ); //向内核注册块设备驱动
add_disk(simp_blkdev_disk); return ; err_alloc_disk:
blk_cleanup_queue(simp_blkdev_queue);
blk_init_queue:
return ret;
}

  如果要用函数elevator_init来设置调度器,就必须先保存原来blk_init_queue()帮我们申请的默认调度器,然后设置队列中的指向调度器的elevator指针为NULL(注意:设置指针为NULL是必须的,要不然函数elevator_init会不做任何事情直接返回),最后才是调用elevator_init(simp_blkdev_queue, "noop")来设置,如果设置成功则调用elevator_exit来释放原来的调度器。具体代码如下(颜色为红色的代码是选择调度器代码):

 static int __init simp_blkdev_init(void)
{
int ret;
struct elevator_queue *elv_old; //分配一个请求队列
simp_blkdev_queue = blk_init_queue(simp_blkdev_do_request, NULL);
if(!simp_blkdev_queue)
{
ret = -ENOMEM;
goto blk_init_queue;
} elv_old = simp_blkdev_queue->elevator;
simp_blkdev_queue->elevator = NULL;
//更换IO调度器
if (IS_ERR_VALUE(elevator_init(simp_blkdev_queue, "noop")))
printk(KERN_WARNING "Switch elevator failed, using default\n");
else
elevator_exit(elv_old);
//分配一个 gendisk 结构,有一个分区
simp_blkdev_disk = alloc_disk();
if(!simp_blkdev_disk)
{
ret = -ENOMEM;
goto err_alloc_disk;
} //填充 gendisk 主要结构成员
strcpy(simp_blkdev_disk->disk_name, SIMP_BLKDEV_DISKNAME);
simp_blkdev_disk->major = SIMP_BLKDEV_DEVICEMAJOR;
simp_blkdev_disk->first_minor = ;
simp_blkdev_disk->fops = &simp_blkdev_fops;
simp_blkdev_disk->queue = simp_blkdev_queue;
set_capacity(simp_blkdev_disk, SIMP_BLKDEV_BYTES >> ); //向内核注册块设备驱动
add_disk(simp_blkdev_disk); return ; err_alloc_disk:
blk_cleanup_queue(simp_blkdev_queue);
blk_init_queue:
return ret;
}

编写简单的ramdisk(选择IO调度器)的更多相关文章

  1. 如何选择IO调度器

    概述 由于对multi-quque的IO调度算法不太熟悉,为了避免误人子弟,本文暂时只会介绍如何选择single-queue的IO调度算法.等将来对multi-queue有充分认识后再补充. 如果不清 ...

  2. 编写简单的ramdisk(无请求队列)

    最近在研究块设备驱动的编写,看了赵磊大牛的<写一个块设备驱动>,受益匪浅,虽然能看懂里面说的,但动手写写代码还是能加深理解的,下面实现的ramdisk写的很简单,如果有错误,欢迎大牛们指正 ...

  3. Linux IO Scheduler(Linux IO 调度器)

    每个块设备或者块设备的分区,都对应有自身的请求队列(request_queue),而每个请求队列都可以选择一个I/O调度器来协调所递交的request.I/O调度器的基本目的是将请求按照它们对应在块设 ...

  4. Linux IO调度器相关算法介绍(转)

    IO调度器(IO Scheduler)是操作系统用来决定块设备上IO操作提交顺序的方法.存在的目的有两个,一是提高IO吞吐量,二是降低IO响应时间.然而IO吞吐量和IO响应时间往往是矛盾的,为了尽量平 ...

  5. Linux IO 调度器

    Linux IO Scheduler(Linux IO 调度器) 每个块设备或者块设备的分区,都对应有自身的请求队列(request_queue),而每个请求队列都可以选择一个I/O调度器来协调所递交 ...

  6. IO调度器原理介绍

    IO调度器(IO Scheduler)是操作系统用来决定块设备上IO操作提交顺序的方法.存在的目的有两个,一是提高IO吞吐量,二是降低IO响应时间.然而IO吞吐量和IO响应时间往往是矛盾的,为了尽量平 ...

  7. Linux IO Scheduler(Linux IO 调度器)【转】

    每个块设备或者块设备的分区,都对应有自身的请求队列(request_queue),而每个请求队列都可以选择一个I/O调度器来协调所递交的request.I/O调度器的基本目的是将请求按照它们对应在块设 ...

  8. IO调度器

    由于对blktrace的好奇,来到了block层.通过阅读block层的代码,自己的几个错误认知被纠正,比如 一) 同步操作时,进程是在驱动中睡觉真实情况是:进程在文件系统睡觉 二) 对同一个数据块的 ...

  9. 编写简单的ramdisk(有请求队列)

    前言 前面用无请求队列实现的ramdisk的驱动程序虽然申请了请求队列,但实际上没用上,因为ramdisk不像实际的磁盘访问速度慢需要缓存,ramdisk之间使用内存空间,所以就没用请求队列了.本文将 ...

随机推荐

  1. @Autowired

    1. Spring框架中进行注入式,使用@Autowired. @Autowired可以对成员变量.方法和构造函数进行标注,来完成自动装配的工作,这里必须明确:@Autowired是根据类型进行自动装 ...

  2. 可变字符串NSMutableString

    //可变字符串继承自字符串 //拼接 NSMutableString *string = [NSMutableString string]; [string appendString:@"今 ...

  3. 关于 Raphael

    Raphael Javascript 是一个 Javascript的矢量库. 2010年6月15日,著名的JavaScript库ExtJS与触摸屏代码库项目jQTouch,以及SVG.VML处理库Ra ...

  4. sass

    本文来自阮一峰http://www.ruanyifeng.com/blog/2012/06/sass.html 学过CSS的人都知道,它不是一种编程语言. 你可以用它开发网页样式,但是没法用它编程.也 ...

  5. Python之路第一课Day11--随堂笔记(异步IO\数据库\队列\缓存之二)

    一.RabbitMQ队列 1.安装: a.官网: 安装 http://www.rabbitmq.com/install-standalone-mac.html b.安装python rabbitMQ ...

  6. POJ2369 Permutations(置换的周期)

    链接:http://poj.org/problem?id=2369 Permutations Time Limit: 1000MS   Memory Limit: 65536K Total Submi ...

  7. 实例讲解 SQL 注入攻击

    这是一篇讲解SQL注入的实例文章,一步一步跟着作者脚步探索如何注入成功,展现了一次完整的渗透流程,值得一读.翻译水平有限,见谅! 一位客户让我们针对只有他们企业员工和顾客能使用的企业内网进行渗透测试. ...

  8. The Solution of UESTC 2016 Summer Training #1 Div.2 Problem B

    Link http://acm.hust.edu.cn/vjudge/contest/121539#problem/B Description standard input/output Althou ...

  9. linux命令初识

    一.查看当前的目录文件 ls  demo   查看demo目录下的所有文件 ls  -l  demo/test.txt   --查看指定目录(test.txt)的详细内容 二.复制文件 cp   or ...

  10. Base64 转换 %2B 变 空格 解决

    //此方法转换会转换出错 deString.ServerUrlDecode().Replace(" ", "+") //换此方法完美解决 HttpUtility ...