写一个块设备驱动 2

转载 2012年03月30日 15:07:41

第 2章

+---------------------------------------------------+
|                 写一个块设备驱动                   |
+---------------------------------------------------+
| 作者:赵磊                                         |
| email: zhaoleidd@hotmail.com                      |
+---------------------------------------------------+
| 文章版权归原作者所有。                             |
| 大家可以自由转载这篇文章,但原版权信息必须保留。   |
| 如需用于商业用途,请务必与原作者联系,若因未取得   |
| 授权而收起的版权争议,由侵权者自行负责。           |
+---------------------------------------------------+

上一章不但实现了一个最简单的块设备驱动程序,而且可能也成功地吓退了不少准备继续看下去的读者

因为第一章看起来好像太难了

不过读者也不要过于埋怨作者,因为大多数情况下第一次都不是什么好的体验......

对于坚持到这里的读者,这一章中,我们准备了一些简单的内容来犒劳大家

关于块设备与 I/O调度器的关系,我们在上一章中已经有所提及
I/O调度器可以通过合并请求、重排块设备操作顺序等方式提高块设备访问的顺序

就好像吃街边的大排档,如果点一个冷门的品种,可能会等更长的时间,

而如果点的恰好与旁边桌子上刚点的相同,那么会很快上来,因为厨师八成索性一起炒了

然而 I/O调度器和块设备的情况却有一些微妙的区别,大概可以类比成人家点了个西红柿鸡蛋汤你接着

就点了个西红柿炒蛋

聪明的厨师一定会先做你的菜,因为随后可以直接往锅里加水煮汤,可怜比你先来的人喝的却是你的刷

锅水

两个菜一锅煮表现在块设备上可以类比成先后访问块设备的同一个位置,这倒是与 I/O调度器无关,有
空学习 linux缓存策略时可以想想这种情况

一个女孩子换了好多件衣服问我漂不漂亮,而我的评价只要一眼就能拿出来

对方总觉得衣服要牌子好、面料好、搭配合理、要符合个人的气质、要有文化,而我的标准却简单的多 :

越薄越好

所谓臭气相投,我写的块设备驱动程序对I/O调度器的要求大概也是如此

究其原因倒不是因为块设备驱动程序好色,而是这个所谓块设备中的数据都是在内存中的

这也意味着我们的“块设备”读写迅速、并且不存在磁盘之类设备通常面临的寻道时间

因此对这个“块设备”而言,一个复杂的 I/O调度器不但发挥不了丝毫作用,反而其本身将白白耗掉不少内

----------------------- Page 13-----------------------

存和 CPU
同样的情况还出现在固态硬盘、U盘、记忆棒之类驱动中                  将来固态硬盘流行之时,大概就是 I/O调度

器消亡之日了

这里我们试图给我们的块设备驱动选择一个最简单的 I/O调度器
目前linux中包含anticipatory、cfq、deadline和 noop这 4个 I/O调度器
2.6.18之前的 linux默认使用 anticipatory ,而之后的默认使用 cfq
关于这 4个调度器的原理和特性我们不打算在这里介绍,原因是相关的介绍满网都是
但我们还是不能避免在这里提及一下 noop调度器,因为我们马上要用到它
noop顾名思义,是一个基本上不干事的调度器。它基本不对请求进行什么附加的处理,仅仅假惺惺地告

诉通用块设备层:我处理完了

但与吃空饷的公仆不同,noop的存在还是有不少进步意义的。至少我们现在就需要一个不要没事添乱的
I/O调度器

选择一个指定的 I/O调度器需要这个函数:
int elevator_init(struct request_queue *q, char *name);
q是请求队列的指针,name是需要设定的 I/O调度器的名称
如果 name为 NULL ,那么内核会首先尝试选择启动参数"elevator="中指定的调度器,

不成功的话就去选择编译内核时指定的默认调度器,

如果运气太背还是不成功,就去选择 "noop"调度器
不要问我怎么知道的,一切皆在 RTFSC(Read the F**ing Source Code --Linus Torvalds)

对于我们的代码,就是在 simp_blkdev_queue = blk_init_queue(simp_blkdev_do_request, 
NULL)后面加上:
elevator_init(simp_blkdev_queue, "noop");

但问题是在 blk_init_queue()函数中系统已经帮我们申请一个了,因此这里我们需要费点周折,把老

的那个送回去

所以我们的代码应该是:

simp_blkdev_init()函数开头处:
elevator_t *old_e;
blk_init_queue()函数之后:
old_e = simp_blkdev_queue->elevator;
if (IS_ERR_VALUE(elevator_init(simp_blkdev_queue, "noop")))
        printk(KERN_WARNING "Switch elevator failed, using default\n");
else
        elevator_exit(old_e);

为方便阅读并提高本文在 google磁盘中的占用率,我们给出修改后的整个 simp_blkdev_init()函数:

static int __init simp_blkdev_init(void)
{

----------------------- Page 14-----------------------

        int ret;
        elevator_t *old_e;

        simp_blkdev_queue = blk_init_queue(simp_blkdev_do_request, NULL);
        if (!simp_blkdev_queue) {
                ret = -ENOMEM;
                goto err_init_queue;
        }

        old_e = simp_blkdev_queue->elevator;
        if (IS_ERR_VALUE(elevator_init(simp_blkdev_queue, "noop")))
                printk(KERN_WARNING "Switch elevator failed, using default\n");
        else
                elevator_exit(old_e);

        simp_blkdev_disk = alloc_disk(1);
        if (!simp_blkdev_disk) {
                ret = -ENOMEM;
                goto err_alloc_disk;
        }

        strcpy(simp_blkdev_disk->disk_name, SIMP_BLKDEV_DISKNAME);
        simp_blkdev_disk->major = SIMP_BLKDEV_DEVICEMAJOR;
        simp_blkdev_disk->first_minor = 0;
        simp_blkdev_disk->fops = &simp_blkdev_fops;
        simp_blkdev_disk->queue = simp_blkdev_queue;
        set_capacity(simp_blkdev_disk, SIMP_BLKDEV_BYTES>>9);
        add_disk(simp_blkdev_disk);

        return 0;

err_alloc_disk:
        blk_cleanup_queue(simp_blkdev_queue);
err_init_queue:
        return ret;
}

本章的改动很小,我们现在测试一下这段代码:

首先我们像原先那样编译模块并加载:

# make
make -C /lib/modules/2.6.18-53.el5/build 
SUBDIRS=/root/test/simp_blkdev/simp_blkdev_step2 modules

----------------------- Page 15-----------------------

make[1]: Entering directory `/usr/src/kernels/2.6.18-53.el5-i686'
  CC [M]  /root/test/simp_blkdev/simp_blkdev_step2/simp_blkdev.o
  Building modules, stage 2.
  MODPOST
  CC      /root/test/simp_blkdev/simp_blkdev_step2/simp_blkdev.mod.o
  LD [M]  /root/test/simp_blkdev/simp_blkdev_step2/simp_blkdev.ko
make[1]: Leaving directory `/usr/src/kernels/2.6.18-53.el5-i686'
# insmod simp_blkdev.ko
#
然后看一看咱们的这个块设备现在使用的 I/O调度器:
# cat /sys/block/simp_blkdev/queue/scheduler
[noop] anticipatory deadline cfq
#

看样子是成功了

哦,上一章中忘了看老程序的调度器信息了,这里补上老程序的情况:

# cat /sys/block/simp_blkdev/queue/scheduler
noop anticipatory deadline [cfq]
#

OK ,我们完成简单的一章,并且用事实说明了作者并没有在开头撒谎

当然,作者也会力图让接下来的章节同样比小说易读

<未完,待续>


写一个块设备驱动(2)

第2章 +---------------------------------------------------+ |                 写一个块设备驱动      ...
  • newnewman80
  • newnewman80
  • 2011年11月09日 10:02
  • 724

写一个块设备驱动程序

----------------------- Page 1----------------------- 第 1章 +----------------------------------...
  • leopard21
  • leopard21
  • 2014年03月01日 00:16
  • 1203

通过内存模拟硬盘实现一个简单的块设备驱动

本文的主要工作是通过硬盘来模拟内存,按照块设备驱动编程的框架实现一个简单的块设备驱动程序。 一、前期的准备工作 1、基本开发环境 Linux内核版本:Linux-3.4.10 开发板 ...
  • TECH_PRO
  • TECH_PRO
  • 2017年05月22日 12:54
  • 728

写一个块设备驱动

第 8章 +---------------------------------------------------+ |                 写一个块设备驱动          ...
  • bm7623
  • bm7623
  • 2012年03月30日 15:17
  • 388

RAMDISK块设备驱动程序

from: http://blog.163.com/hjw_vc/blog/static/1148310352009104952466/ ram、loop、网络设备等驱动通常使用自己编写的m...
  • damotiansheng
  • damotiansheng
  • 2015年03月31日 13:58
  • 1081

块设备驱动架构分析

1. 块设备概念:块设备是指只能以块为单位进行访问的设备,块的大小一般是512个字节的整数倍。常见的块设备包括硬件,SD卡,光盘等。 2. 块设备驱动的系统架构 2.1 系统架构---VFS VFS是...
  • coding__madman
  • coding__madman
  • 2016年06月06日 22:34
  • 3866

学写块设备驱动(三)----踢开IO调度器,自己处理bio(上)

前两篇我们编写了在内存中的最简单的块设备驱动程序,并为其更换了我们心仪的’noop‘IO调度器。本篇我们试着搞清楚内核的块设备层在这里为我们做的事情,以及我们如何做点自己想做的事情。 其实,我们前面...
  • magic_coder
  • magic_coder
  • 2012年01月09日 14:12
  • 3304

块设备驱动程序之一

一、块设备概述 linux支持的两种重要的设备类型分别是字符设备和块设备,块设备可以随机地以固定大小的块传送数据。与字符设备相比,块设备有以下几个特殊之处: 块设备可以从数据的任何位置进行访问块数据...
  • goodluckwhh
  • goodluckwhh
  • 2014年02月10日 23:41
  • 4241

scsi块设备驱动层处理

1.6.3 scsi块设备驱动层处理好了,了解完必要的scsi设备驱动知识以后,我们就可以安心分析scsi_request_fn函数了。大家回忆一下对,这个函数指针通过几次传递并最终在blk_init...
  • yunsongice
  • yunsongice
  • 2011年02月01日 01:01
  • 6705

一个简单的块设备驱动的实现

一个简单的块设备驱动的实现 这篇文章系列来自原创作者:赵磊,感谢这位作者,链接为:http://bbs.chinaunix.net/thread-2017377-1-1.html ...
  • chenglinhust
  • chenglinhust
  • 2013年05月09日 11:23
  • 1734
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:写一个块设备驱动 2
举报原因:
原因补充:

(最多只允许输入30个字)