#include <linux/kernel.h> #include <linux/module.h> #include <linux/init.h> #include <linux/errno.h> #include <linux/blkdev.h> #include <linux/bio.h>
#define RAMDISK_MAJOR 0 /*主设备号设置0让内核动态产生一个主设备号*/ #define RAMDISK_NAME "my2440_ramdisk" /*设备名称*/ #define RAMDISK_SIZE (4 * 1024 * 1024) /*虚拟磁盘的大小,共4M*/
static int ramdisk_major = RAMDISK_MAJOR; /*用来保存动态分配的主设备号*/ static struct class *ramdisk_class; /*定义一个设备类,好在/dev下动态生成设备节点*/
static struct gendisk *my2440_ramdiak; /*定义一个gendisk结构体用来表示一个磁盘设备*/ static struct request_queue *ramdisk_queue; /*定义磁盘设备的请求队列*/
unsigned char *disk_data;/*定义一个指针来表示ramdisk块设备在内存中的域*/
/*块设备驱动操作结构体,其实不需要做什么操作,这里就设置为空*/ static struct block_device_operations ramdisk_fops = { .owner = THIS_MODULE, };
static int __init ramdisk_init(void) { int ret;
/*块设备驱动注册, 注意这个块设备驱动的注册在2.6内核中是可选的, 该函数由内核提供。这里使用是为了获得一个动态生成的主设备号*/ ramdisk_major = register_blkdev(RAMDISK_MAJOR, RAMDISK_NAME); if(ramdisk_major <= 0) { return ramdisk_major; }
/*动态创建一个设备节点,跟字符型设备一样*/ ramdisk_class = class_create(THIS_MODULE, RAMDISK_NAME); if(IS_ERR(ramdisk_class)) { ret = -1; goto err_class; } device_create(ramdisk_class, NULL, MKDEV(ramdisk_major, 0), NULL, RAMDISK_NAME);
/*RamDisk属真正随机访问的设备,因此不使用请求队列的处理方式,而使用制造请求的方式*/ ramdisk_queue = blk_alloc_queue(GFP_KERNEL);/*分配ramdisk_queue*/
if(!ramdisk_queue) { ret = -ENOMEM; goto err_queue; } blk_queue_make_request(ramdisk_queue, &ramdisk_make_request);/*绑定请求制造函数*/
/*分配gendisk,该函数由内核提供,参数为磁盘设备的次设备号数量(或者磁盘的分区数量) 注意一个分区就代表一个次设备,这里指定数量后以后就不能被修改了*/ my2440_ramdiak = alloc_disk(1);
if(!my2440_ramdiak) { ret = -ENOMEM; goto err_alloc; }
/*初始化gendisk*/ my2440_ramdiak->major = ramdisk_major; /*这里指定的主设备号就是在上面动态获取的主设备号*/ my2440_ramdiak->first_minor = 0; /*指定第一个次设备号为0*/ my2440_ramdiak->fops = &ramdisk_fops; /*指定块设备驱动对底层硬件操作的结构体指针,定义在后面来讲*/ my2440_ramdiak->queue = ramdisk_queue; /*指定初始化好的请求队列*/ sprintf(my2440_ramdiak->disk_name, RAMDISK_NAME);/*指定磁盘设备的名称*/
/*设置磁盘设备的容量大小,该函数由内核提供。 注意该函数是以512字节为1个扇区单位进行处理的,因为内核要求如此*/ set_capacity(my2440_ramdiak, RAMDISK_SIZE >> 9);/*右移9位就是除以512*/
/*添加gendisk到系统中, 该函数由内核提供*/ add_disk(my2440_ramdiak);
return 0;
/*错误处理*/ err_class: unregister_blkdev(ramdisk_major, RAMDISK_NAME); err_queue: device_destroy(ramdisk_class, MKDEV(ramdisk_major, 0)); class_destroy(ramdisk_class); err_alloc: blk_cleanup_queue(ramdisk_queue);
return ret; }
static void __exit ramdisk_exit(void) { /*删除磁盘设备*/ del_gendisk(my2440_ramdiak); put_disk(my2440_ramdiak);
/*清除请求队列*/ blk_cleanup_queue(ramdisk_queue);
/*清除设备类*/ device_destroy(ramdisk_class, MKDEV(ramdisk_major, 0)); class_destroy(ramdisk_class);
/*注销块设备*/ unregister_blkdev(ramdisk_major, RAMDISK_NAME); }
module_init(ramdisk_init); module_exit(ramdisk_exit);
MODULE_LICENSE("GPL"); MODULE_AUTHOR("Huang Gang"); MODULE_DESCRIPTION("My2440 RamDisk Driver"); |