Linux中块设备驱动程序分析

基于《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中块设备驱动程序分析,布布扣,bubuko.com

时间: 2024-10-11 21:46:22

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

linux下块设备驱动程序

块设备不能向字符设备那样访问,而是要先将请求放入队列,优化调整顺序后再执行,这种访问方式称为"电梯调度算法". 本篇文章通过ramdisk.nand flash.nor flash来讲解如何写块设备驱动程序. 一.ramdisk 1.因为块设备驱动程序是将请求放入队列然后调整顺序后执行,所以我们需要先定义请求队列: static unsigned char *ramblock_buf; ramblock_buf = kzalloc(RAMBLOCK_SIZE, GFP_KERNEL);

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

在LINUX系统文件类型分类的文章中我们提到了 块设备 和 字符设备文件,那么什么是块设备 字符设备文件呢?他们之间有什么本质上的区别呢? 设备文件分为 Block(块) Device Driver 和 Character(字符)Device Drive 两类.Character Device Drive又被称为字符设备或裸设备 raw  devices. Block Device Driver称为块设备. 区别: Block Device Driver 是以固定大小长度来传送转移资料,Char

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

#define SBULL_MINORS  16         /* 每个sbull设备所支持的次设备号的数量 */ #define KERNEL_SECTOR_SIZE 512  // 本地定义的常量,使用该常量进行内核512字节到实际 // 扇区大小的转换 #define INVALIDATE_DELAY  30*HZ 块设备的核心数据结构(the internal representation of our device): struct sbull_dev{ int size;    

11 Linux 块设备驱动程序

参考:https://www.cnblogs.com/big-devil/p/8590007.html Linux 块设备驱动程序 概念补充: 块 扇区是硬件数据传输的基本单元,块则是虚拟文件系统传输数据的基本单位.Linux内核中,块的大小必须是2的次幂,但不能超过一个页(4K)的大小. 段 同一物理页面中的硬盘存储介质上连续的多个块组成一个段.段的大小与块的个数有关,段包含多个块,块包含多个扇区.段在内核中由bio_vec结构体描述,多个段的信息存放于结构体bio中的biz_io_vec数组

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

简介 一个块设备驱动程序主要通过传输固定大小的随机数据来访问设备 Linux内核视块设备为与字符设备相异的基本设备类型 Linux块设备驱动程序接口使得块设备可以发挥其最大的功效,但是其复杂程序又是编程者必须面对的一个问题 一个数据块指的是固定大小的数据,而大小的值由内核确定 数据块的大小通常是4096个字节,但是可以根据体系结构和所使用的文件系统进行改变 与数据块对应的是扇区,它是由底层硬件决定大小的一个块,内核所处理的设备扇区大小是512字节 如果要使用不同的硬件扇区大小,用户必须对内核的扇

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

扇区: 1.硬盘控制器将磁盘看成一大组扇区2.扇区就是一组相邻字节3.扇区按照惯例大小设置位512字节4.存放在块设备中的数据是通过它们在磁盘上的位置来标识,即首个扇区的下标和扇区的数目.5.扇区是硬件设备传送数据到基本单位. 块:1.块是VFS和文件系统传送数据到基本单位.它对应磁盘上一个或者多个相邻扇区.2.内核访问一个文件内容时,它先从磁盘上读文件的磁盘索引节点所在的块3.Linux中,块必须是2的幂,且不能超过一个页框(一般4kB),还必须是扇区大小的整数倍.4.对块设备文件的读写操作时

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

字符设备驱动程序 应用程序是调用C库中的open read write等函数.而为了操作硬件,所以引入了驱动模块. 构建一个简单的驱动,有一下步骤. 1. 创建file_operations 2. 申请设备号 3. 注册字符设备驱动, 4. 驱动入口 5. 驱动出口 检查数据是否到来的方式: 1. 查询方式 2. 休眠唤醒方式 如果设备出现异常而无法唤醒时,则将永远处于休眠状态. 3. poll机制 如果没有被唤醒,则在一定时间内可自己唤醒. 4. 异步通知(信号) 而以上的几种方式通用性不高,

20150310 块设备驱动程序

20150310 块设备驱动程序 2015-03-10 李海沿 接下来我们来实现块设备驱动程序. 一.块设备结构体 1. file_operations 结构体 和字符设备驱动中file_operations 结构体类似,块设备驱动中也有一个 block_device_operations 结构体,它的声明位于/include/linux 录下的fs.h 文件中,它是对 块操作的集合. struct block_device_operations{ int(*open)(struct inode

【Linux 驱动】设备驱动程序再理解

学习设备驱动编程也有一段时间了,也写过了几个驱动程序,因此有对设备驱动程序有了一些新的理解和认识,总结一下.学习设备驱动编程也有一段时间了,也写过了几个驱动程序,因此有对设备驱动程序有了一些新的理解和认识,总结一下. ★什么是驱动程序 刚开始学习设备驱动程序的时候,产生了许多的问题.什么是驱动程序?驱动程序是干嘛的?它是如何工作的?它又是如何跟操作系统联系起来的?一系列的问题,现在有些地方还是不一定清楚,但是相比起刚开始的那个阶段,感觉自己还是清楚了很多. 设备驱动程序说白了(实质)就是为应用程