编写简单的ramdisk(选择IO调度器)
前言
目前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调度器)的更多相关文章
- 如何选择IO调度器
概述 由于对multi-quque的IO调度算法不太熟悉,为了避免误人子弟,本文暂时只会介绍如何选择single-queue的IO调度算法.等将来对multi-queue有充分认识后再补充. 如果不清 ...
- 编写简单的ramdisk(无请求队列)
最近在研究块设备驱动的编写,看了赵磊大牛的<写一个块设备驱动>,受益匪浅,虽然能看懂里面说的,但动手写写代码还是能加深理解的,下面实现的ramdisk写的很简单,如果有错误,欢迎大牛们指正 ...
- Linux IO Scheduler(Linux IO 调度器)
每个块设备或者块设备的分区,都对应有自身的请求队列(request_queue),而每个请求队列都可以选择一个I/O调度器来协调所递交的request.I/O调度器的基本目的是将请求按照它们对应在块设 ...
- Linux IO调度器相关算法介绍(转)
IO调度器(IO Scheduler)是操作系统用来决定块设备上IO操作提交顺序的方法.存在的目的有两个,一是提高IO吞吐量,二是降低IO响应时间.然而IO吞吐量和IO响应时间往往是矛盾的,为了尽量平 ...
- Linux IO 调度器
Linux IO Scheduler(Linux IO 调度器) 每个块设备或者块设备的分区,都对应有自身的请求队列(request_queue),而每个请求队列都可以选择一个I/O调度器来协调所递交 ...
- IO调度器原理介绍
IO调度器(IO Scheduler)是操作系统用来决定块设备上IO操作提交顺序的方法.存在的目的有两个,一是提高IO吞吐量,二是降低IO响应时间.然而IO吞吐量和IO响应时间往往是矛盾的,为了尽量平 ...
- Linux IO Scheduler(Linux IO 调度器)【转】
每个块设备或者块设备的分区,都对应有自身的请求队列(request_queue),而每个请求队列都可以选择一个I/O调度器来协调所递交的request.I/O调度器的基本目的是将请求按照它们对应在块设 ...
- IO调度器
由于对blktrace的好奇,来到了block层.通过阅读block层的代码,自己的几个错误认知被纠正,比如 一) 同步操作时,进程是在驱动中睡觉真实情况是:进程在文件系统睡觉 二) 对同一个数据块的 ...
- 编写简单的ramdisk(有请求队列)
前言 前面用无请求队列实现的ramdisk的驱动程序虽然申请了请求队列,但实际上没用上,因为ramdisk不像实际的磁盘访问速度慢需要缓存,ramdisk之间使用内存空间,所以就没用请求队列了.本文将 ...
随机推荐
- MongoDB常用命令
本文整理了一年多以来我常用的MongoDB操作,涉及mongo-shell.pymongo,既有运维层面也有应用层面,内容有浅有深,这也就是我从零到熟练的历程. MongoDB的使用之前也分享过一篇, ...
- winform控件在Enable=false的情况下改变它的字体颜色
[System.Runtime.InteropServices.DllImport("user32.dll ")] public static extern int ...
- css多行显示省略号
首先说css多行显示省略号和单行文本省略号: 我们知道,单行显示省略号时,我们首先需要设置容器的宽度width:value(具体的值),然后强制文本在一行内显示,即white-spacing:nowr ...
- iOS地图
地图 1.主要用到了地图展示和定位功能 CoreLocation框架的使用: 导入头文件 #import <CoreLocation/CoreLocation.h>CoreL ...
- node-webkit安装及简单实现
遇到一个客户说不要登录网页访问系统,说是不安全,要做成像是QQ这样的客户端. 这让我很为难啊,项目都快做好了,不可能让我重新做吧,再说C++什么的我也不会啊, 于是我接触了node-webkit,并觉 ...
- 自定义 TableViewCell 的分割线
刚开始自定义 tableViewCell 的时候,用的是直接在 cell 上加一张 imageView 的方法,如果在点击 cell 的时候有页面的跳转,这样做没什么问题,但是,如果在点击 cell ...
- Python之路第一课Day7--随堂笔记(面向对象编程进阶...未完待续 )
本节内容: 面向对象高级语法部分 静态方法.类方法.属性方法 类的特殊方法 反射 异常处理 Socket开发基础 作业:开发一个支持多用户在线的FTP程序 面向对象高级语法部分 一.静态方法 通过@s ...
- css简单评论页面
<!DOCTYPE html> <html> <head> <meta charset='utf-8'> <style> *{margin: ...
- CentOS6.4安装JDK1.7
安装说明 1.安装环境: CentOS6.4 64位系统 2.安装方式:rpm安装 3.软 件 包:jdk-7u71-linux-x64.rpm 4.下载地址:http://www.oracle.co ...
- C# 匿名对象随笔
最新更新请访问: http://denghejun.github.io C#中匿名对象的一般写法是这样的: object o=new {Name="TestName"}; ...