基于《Linux设备驱动程序》书中的sbull程序以对Linux块设备驱动总结分析。

開始之前先来了解这个块设备中的核心数据结构:

struct sbull_dev {

        int size;                       /* Device size in sectors */

        u8 *data;                       /* The data array */

        short users;                    /* How many users */

        short media_change;             /* Flag a media change? */

        spinlock_t lock;                /* For mutual exclusion */

        struct request_queue *queue;    /* The device request queue */

        struct gendisk *gd;             /* The gendisk structure */

        struct timer_list timer;        /* For simulated media changes */

};

在这个结构中,struct request_queue与 struct gendisk 是这个结构中的重要成员,

也是块设备中的重要结构,这个文章中的大部分阐述都是基于这两个结构的操作。

一.流程:

块设备驱动也是从init函数開始的,所以分析也从这里開始。

第一步:

    register_blkdev(sbull_major, "sbull");

先注冊块设备,第一个參数是设备号,为0表完动态分配,第二个为设备名。

第二步:

    Devices = kmalloc(ndevices*sizeof (struct sbull_dev), GFP_KERNEL);

创建这个块设备的核心数据结构,也就是这个块设备的对象实体,创建了ndevice这样

的实体。

第三步:

    setup_device(Devices + i, i);

说白了,就是初始化实体,并把它加入到系统的block层中去。这个步骤非常重要,它完

成以下面一些操作:

1.初始化一个自旋锁。    

    spin_lock_init(&dev->lock);

2.分配一个请求队列,并用1中的自旋锁来控制对队列的訪问。

    dev->queue = blk_init_queue(sbull_full_request, &dev->lock);

3.分配,初始化及安装对应的gendisk结构。

    dev->gd = alloc_disk(SBULL_MINORS);

    if (! dev->gd) {

        printk (KERN_NOTICE "alloc_disk failure/n");

        goto out_vfree;

    }

    dev->gd->major = sbull_major;

    dev->gd->first_minor = which*SBULL_MINORS;

    dev->gd->fops = &sbull_ops;

    dev->gd->queue = dev->queue;

    dev->gd->private_data = dev;

    snprintf (dev->gd->disk_name, 32, "sbull%c", which + 'a');

    set_capacity(dev->gd, nsectors*(hardsect_size/KERNEL_SECTOR_SIZE));

4.最后add_disk完毕整个初始化过程,这步一定要在初始化的最后再调用,由于

  add_disk后,可能就会调用磁盘的操作函数,假设初始化还没有完毕就会出错。

二.块设备操作 struct block_device_operations 结构分析:

sbull模块中的该结构:

static struct block_device_operations sbull_ops = {

    .owner           = THIS_MODULE,

    .open              = sbull_open,

    .release           = sbull_release,

    .media_changed   = sbull_media_changed,

    .revalidate_disk = sbull_revalidate,

    .ioctl             = sbull_ioctl

};

open与release这两个函数就不再详细分析,它们有一个重要功能就是添加用户计数和

降低用户计数。media_changed 和revalidata_disk即是对可移动介质的支持,像u盘等

等这些可移动,即插即用的设备就应该实现这两个函数。media_changed是检查介质是

否改变,发迹即返回非零,revalidate_disk即介质改变后运行。它们之间怎样联系我

们不用管,我们主要实现这个函数的实体就可以。

ioctl函数,ioctl函数的功能也简化了,可实际的磁盘设备大多也主要是实现对磁盘信

息的查询。

三.请求处理。

    块设备驱动程序的核心是请求处理部分,是块设备驱动的难点。设计得好否直接关

系到设备的性能。

    我们看在安装块设备实体的时候,初始化了一个请求队列:

    dev->queue = blk_init_queue(sbull_full_request, &dev->lock);

这个操作就是把生成的请求队列dev->queue与请求函数sbull_full_request绑定在一

起。sbull中的request函数:

static void sbull_full_request(request_queue_t *q)

{

    struct request *req;

    int sectors_xferred;

    struct sbull_dev *dev = q->queuedata;

    while ((req = elv_next_request(q)) != NULL) {

        if (! blk_fs_request(req)) {

            printk (KERN_NOTICE "Skip non-fs request/n");

            end_request(req, 0);

            continue;

        }

        sectors_xferred = sbull_xfer_request(dev, req);

        if (! end_that_request_first(req, 1, sectors_xferred)) {

            blkdev_dequeue_request(req);

            end_that_request_last(req);

        }

    }

}

req = elv_next_request(q) 获取队列中第一个未完毕的请求,两次调用而没有

执行end_that_request_last或者end_request时得到的是同样的结果,由于它不会删除

队列中的请求。仅仅有结束该请求,才会得到下一个请求。sbull_xfer_request在这里即

是实际的传输数据。

一个实际的块设备请求处理要这些要复杂得多,那就要更深入了解request结构,bio结

构,队列结构等等。但在这里先不深入去讨论。

Linux中块设备驱动程序分析的更多相关文章

  1. LINUX中块设备文件和字符设备文件的本质区别

    在LINUX系统文件类型分类的文章中我们提到了 块设备 和 字符设备文件,那么什么是块设备 字符设备文件呢?他们之间有什么本质上的区别呢? 设备文件分为 Block(块) Device Driver ...

  2. 嵌入式驱动开发之--- 虚拟磁盘SBULL块设备驱动程序分析

     #define SBULL_MINORS  16         /* 每个sbull设备所支持的次设备号的数量 */  #define KERNEL_SECTOR_SIZE 512  // 本地定 ...

  3. [中英对照]User-Space Device Drivers in Linux: A First Look | 初识Linux用户态设备驱动程序

    如对Linux用户态驱动程序开发有兴趣,请阅读本文,否则请飘过. User-Space Device Drivers in Linux: A First Look | 初识Linux用户态设备驱动程序 ...

  4. 嵌入式Linux驱动学习之路(二十一)字符设备驱动程序总结和块设备驱动程序的引入

    字符设备驱动程序 应用程序是调用C库中的open read write等函数.而为了操作硬件,所以引入了驱动模块. 构建一个简单的驱动,有一下步骤. 1. 创建file_operations 2. 申 ...

  5. 简单linux块设备驱动程序

    本文代码参考<LINUX设备驱动程序>第十六章 块设备驱动程序 本文中的“块设备”是一段大小为PAGE_SIZE的内存空间(两个扇区,每个扇区512字节) 功能:向块设备中输入内容,从块设 ...

  6. 《Linux Device Drivers》第十六章 块设备驱动程序——note

    基本介绍 块设备驱动程序通过主传动固定大小数据的随机访问设备 Linux核心Visual块设备作为基本设备和不同的字符设备类型 Linux块设备驱动程序接口,使块设备最大限度地发挥其效用.一个问题 一 ...

  7. 深入理解Linux内核-块设备驱动程序

    扇区: 1.硬盘控制器将磁盘看成一大组扇区2.扇区就是一组相邻字节3.扇区按照惯例大小设置位512字节4.存放在块设备中的数据是通过它们在磁盘上的位置来标识,即首个扇区的下标和扇区的数目.5.扇区是硬 ...

  8. (linux)块设备驱动程序

      1.4.1  Linux块设备驱动程序原理(1) 顾名思义,块设备驱动程序就是支持以块的方式进行读写的设备.块设备和字符设备最大的区别在于读写数据的基本单元不同.块设备读写数据的基本单元为块,例如 ...

  9. linux系统下块设备驱动程序

    顾名思义,块设备驱动程序就是支持以块的方式进行读写的设备.块设备和字符设备最大的区别在于读写数据的基本单元不同.块设备读写数据的基本单元为块,例 如磁盘通常为一个sector,而字符设备的基本单元为字 ...

随机推荐

  1. JavaScript快速入门(一)——JavaScript概览

    JavaScript是什么? JavaScript的诞生 在1995年前后,当时世界上的主流带宽为28.8Kbps,现在世界平均下载带宽为21.9Mbps(数据来源于http://www.netind ...

  2. list view Item 里面有ImageButton

    list view Item 里面有ImageButton listview 的item中有ImageButton, 或者 Button. 目的: ImageButton 和 Button的click ...

  3. 搜索:POJ2251&POJ1426&POJ3087&POJ2488

    图的遍历也称为搜索,就是从图中某个顶点出发,沿着一些边遍历图中所有的顶点,且每个顶点仅被访问一次,遍历可采取两种不同的方式:深度优先搜索(DFS)和广度优先搜索(BFS). 1.DFS算法思想` 从顶 ...

  4. [docker]coreOS与atomic对照

    声明: 本博客欢迎转发,但请保留原作者信息! 博客地址:http://blog.csdn.net/halcyonbaby 内容系本人学习.研究和总结,如有雷同,实属荣幸! 摘自https://majo ...

  5. 七内部排序算法汇总(插入排序、Shell排序、冒泡排序、请选择类别、、高速分拣合并排序、堆排序)

    写在前面: 排序是计算机程序设计中的一种重要操作,它的功能是将一个数据元素的随意序列,又一次排列成一个按keyword有序的序列.因此排序掌握各种排序算法很重要. 对以下介绍的各个排序,我们假定全部排 ...

  6. Windows平台Go调用DLL的坑(居然有这么多没听过的名词)

    最近的项目中,使用了GO来开发一些服务中转程序.业务比较简单,但是有一些业务需要复用原有C++开发的代码.而在WINDOWS,用CGO方式来集成C/C++代码并不是太方便.所以用DLL把C++的代码封 ...

  7. WebBrowser控件禁用超链接转向、脚本错误提示、默认右键菜单和快捷键

    原文:WebBrowser控件禁用超链接转向.脚本错误提示.默认右键菜单和快捷键 WebBrowser控件禁用超链接转向.脚本错误提示.默认右键菜单和快捷键从 VS2005开始,VS自带的 WebBr ...

  8. [.NET Framework学习笔记]一些概念

    CIL:Common Intermediate Language 公共中间语言 VB.NET 和 C#.NET 编译以后都生成相同的中间语言,程序集就是由CIL组成的,CIL代码也叫做托管代码,因为C ...

  9. SilkTest高级进阶系列9 – 异步执行命令

    我们常常会使用sys_execute函数执行一些外部的程序或者命令来做一些事情,但是由于sys_execute是一个同步的函数,它会等待执行的命令完成后才会返回.在大多数情况下,这个函数足够用了. 但 ...

  10. Linux从用户层到内核层系列 - GNU系列之glibc介绍

    题记:本系列文章的目的是抛开书本从源代码和使用的角度分析Linux内核和相关源代码,byhankswang和你一起玩转linux开发 轻松搞定TCP/IP协议栈,原创文章欢迎交流, byhankswa ...