块设备驱动框架分析(一)

参考:写一个块设备驱动

先上范例代码,用内存模拟块设备。内核模块加载后,测试信息如下:

第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");

 

posted @ 2016-12-18 21:08  bluebluebluesky  阅读(609)  评论(0编辑  收藏  举报