由于真实的块设备如nand,sd卡等读写访问操作比较麻烦,分析起来难度也较大,所以这里我们使用系统中的内存虚拟出一个硬件设备,然后对这个使用块设备驱动对这份内存进行读写。
驱动的详细分析在前面的博客中已经分析过,这里只对块设备相关的,特有的部分也就是驱动入口代码进行一个分析,对驱动中都有的部分就不做解释了。
驱动的入口:
module_init(my_ramblock_init);
static int my_ramblock_init(void)
{
major = register_blkdev(0, "my_ramblock");
if (major < 0)
{
printk("fail to regiser my_ramblock\n");
return -EBUSY;
}
// 实例化
my_ramblock_disk = alloc_disk(1); //次设备个数 ,分区个数 +1
//分配设置请求队列,提供读写能力
my_ramblock_queue = blk_init_queue(do_my_ramblock_request, &my_ramblock_lock);
//设置硬盘属性
my_ramblock_disk->major = major;
my_ramblock_disk->first_minor = 0;
my_ramblock_disk->fops = &my_ramblock_fops;
sprintf(my_ramblock_disk->disk_name, "my_ramblcok"); // /dev/name
my_ramblock_disk->queue = my_ramblock_queue;
set_capacity(my_ramblock_disk, RAMBLOCK_SIZE / 512);
/* 硬件相关操作 */
my_ramblock_buf = kzalloc(RAMBLOCK_SIZE, GFP_KERNEL);
add_disk(my_ramblock_disk); // 向驱动框架注册一个disk或者一个partation的接口
return 0;
}
1.驱动的注册:
0表示系统动态的分配主设备号,另一个参数为设备名。
major = register_blkdev(0, "my_ramblock");
2.实例化一个结构体指针,将内存分成alloc_disk(1)参数+1个分区;
my_ramblock_disk = alloc_disk(1); //次设备个数 ,分区个数 +1
static struct gendisk *my_ramblock_disk; // 磁盘设备的结构体
而这个结构体是磁盘设备的独有一个设备结构体。
3.实例化请求队列:
my_ramblock_queue = blk_init_queue(do_my_ramblock_request, &my_ramblock_lock);
用来实例化产生一个等待队列,也就是my_ramblock_queue
static struct request_queue *my_ramblock_queue; // 等待队列
将来应用层对本块设备所做的所有的读写操作,都会生成一个request然后被加到这个等待队列。
blk_init_queue函数接收的2个参数,第一个是等待队列的回调函数,这个函数是驱动提供的用来处理等待队列中的request的函数(IO调度层通过电梯算法从等待队列中取出一个request,就会调用这个回调函数来处理这个请求),第二个参数是一个自旋锁,这个自旋锁是要求我们驱动提供给等待队列去使用的。
4.进行设备结构体变量的填充,设置硬件的属性:
填充、设置主设备号;
my_ramblock_disk->major = major;
填充、设置次设备号从0开始设置:
my_ramblock_disk->first_minor = 0;
填充、设置块设备的block_device_operations结构体:
my_ramblock_disk->fops = &my_ramblock_fops;
填充、设置等待队列:
my_ramblock_disk->queue = my_ramblock_queue;
设置块设备的大小:
set_capacity(my_ramblock_disk, RAMBLOCK_SIZE / 512);
这里的大小以扇区为单位,第一个参数是前面填充设置的设备结构体变量。
5.给虚拟的设备进行内存的分配:(实际驱动中无此步骤)
my_ramblock_buf = kzalloc(RAMBLOCK_SIZE, GFP_KERNEL);
在前面只是定义了一个内存指针,并未进行实例化:
static unsigned char *my_ramblock_buf;
在这里使用堆内存,动态的分配内存 ,分配的大小就是RAMBLOCK_SIZE=1M
#define RAMBLOCK_SIZE (1024*1024)
6.调用接口注册一个块设备文件:
add_disk(my_ramblock_disk);
代码来源于ldd3书中,特别鸣谢!
End。。。。。。