块设备驱动框架分析(一)
参考:写一个块设备驱动
先上范例代码,用内存模拟块设备。内核模块加载后,测试信息如下:
第94行 major = register_blkdev(0, "ramblock"); /* cat /proc/devices */
第97行 sprintf(ramblock_disk->disk_name, "ramblock");/*ls -l /dev/ramblock*/
1 #include <linux/module.h> 2 #include <linux/moduleparam.h> 3 #include <linux/init.h> 4 5 #include <linux/sched.h> 6 #include <linux/kernel.h> /* printk() */ 7 #include <linux/slab.h> /* kmalloc() */ 8 #include <linux/fs.h> /* everything... */ 9 #include <linux/errno.h> /* error codes */ 10 #include <linux/timer.h> 11 #include <linux/types.h> /* size_t */ 12 #include <linux/fcntl.h> /* O_ACCMODE */ 13 #include <linux/hdreg.h> /* HDIO_GETGEO */ 14 #include <linux/kdev_t.h> 15 #include <linux/vmalloc.h> 16 #include <linux/genhd.h> 17 #include <linux/blkdev.h> 18 #include <linux/buffer_head.h> /* invalidate_bdev */ 19 #include <linux/bio.h> 20 21 static struct gendisk * ramblock_disk; 22 static struct request_queue * ramblock_queue; 23 24 static int major; 25 26 static DEFINE_SPINLOCK(ramblock_lock); 27 28 #define RAMBLOCK_SIZE (1024*1024) 29 static unsigned char *ramblock_buf; 30 31 static int ramblock_getgeo(struct block_device *bdev, struct hd_geometry *geo) 32 { 33 /* 容量=heads*cylinders*sectors*512 */ 34 geo->heads = 2; 35 geo->cylinders = 32; 36 geo->sectors = RAMBLOCK_SIZE/2/32/512; 37 return 0; 38 } 39 40 41 static struct block_device_operations ramblock_fops = { 42 .owner = THIS_MODULE, 43 .getgeo = ramblock_getgeo, 44 }; 45 46 static void do_ramblock_request(struct request_queue * q) 47 { 48 static int r_cnt = 0; 49 static int w_cnt = 0; 50 struct request *req; 51 52 //printk("do_ramblock_request %d\n", ++cnt); 53 54 55 while ((req = blk_fetch_request(q)) != NULL) { 56 /* 数据传输三要素: 源,目的,长度 */ 57 /* 源/目的: */ 58 unsigned long offset =blk_rq_pos(req) * 512; 59 60 /* 目的/源: */ 61 // req->buffer 62 63 /* 长度: */ 64 unsigned long len = blk_rq_cur_sectors(req) * 512; 65 66 if (rq_data_dir(req) == READ) 67 { 68 printk("do_ramblock_request read %d\n", ++r_cnt); 69 memcpy(req->buffer, ramblock_buf+offset, len); 70 } 71 else 72 { 73 printk("do_ramblock_request write %d\n", ++w_cnt); 74 memcpy(ramblock_buf+offset, req->buffer, len); 75 } 76 77 if(!__blk_end_request_cur(req, 0)) 78 break; 79 } 80 } 81 82 83 static int ramblock_init(void) 84 { 85 /* 1. 分配一个gendisk结构体 */ 86 ramblock_disk = alloc_disk(16); /* 次设备号个数: 分区个数+1 */ 87 88 /* 2. 设置 */ 89 /* 2.1 分配/设置队列: 提供读写能力 */ 90 ramblock_queue = blk_init_queue(do_ramblock_request, &ramblock_lock); 91 ramblock_disk->queue = ramblock_queue; 92 93 /* 2.2 设置其他属性: 比如容量 */ 94 major = register_blkdev(0, "ramblock"); /* cat /proc/devices */ 95 ramblock_disk->major = major; 96 ramblock_disk->first_minor = 0; 97 sprintf(ramblock_disk->disk_name, "ramblock");/*ls -l /dev/ramblock*/ 98 ramblock_disk->fops = &ramblock_fops; 99 set_capacity(ramblock_disk, RAMBLOCK_SIZE / 512); 100 101 /* 3. 硬件相关操作 */ 102 ramblock_buf = kzalloc(RAMBLOCK_SIZE, GFP_KERNEL); 103 104 /* 4. 注册 */ 105 add_disk(ramblock_disk); 106 107 return 0; 108 } 109 110 static void ramblock_exit(void) 111 { 112 unregister_blkdev(major, "ramblock"); 113 del_gendisk(ramblock_disk); 114 put_disk(ramblock_disk); 115 blk_cleanup_queue(ramblock_queue); 116 117 kfree(ramblock_buf); 118 } 119 120 module_init(ramblock_init); 121 module_exit(ramblock_exit); 122 MODULE_LICENSE("GPL");