码迷,mamicode.com
首页 > 其他好文 > 详细

块设备驱动

时间:2018-08-06 18:29:35      阅读:167      评论:0      收藏:0      [点我收藏+]

标签:switch   通知   exit   memcpy   gen   fcntl   自己   模拟   vma   

 

 

  1 #include <linux/module.h>
  2 #include <linux/moduleparam.h>
  3 #include <linux/init.h>
  4 #include <linux/sched.h>
  5 #include <linux/kernel.h>    /* printk() */
  6 #include <linux/slab.h>        /* kmalloc() */
  7 #include <linux/fs.h>        /* many abount block */
  8 #include <linux/errno.h>    /* error codes */
  9 #include <linux/timer.h>
 10 #include <linux/types.h>    /* size_t */
 11 #include <linux/fcntl.h>    /* O_ACCMODE */
 12 #include <linux/hdreg.h>    /* HDIO_GETGEO */
 13 #include <linux/kdev_t.h>
 14 #include <linux/vmalloc.h>
 15 #include <linux/genhd.h>
 16 #include <linux/blkdev.h>
 17 #include <linux/buffer_head.h>    /* invalidate_bdev */
 18 #include <linux/bio.h>
 19 #define BLOCK_DEVICEMAJOR    COMPAQ_SMART2_MAJOR //块设备文件主设备号  72
 20 #define BLOCK_DISKNAME        "queue_block"    // 块设备名字
 21 #define BLOCK_DEV_BYTES        (1*1024*1024)    //块设备容量 1M 
 22 static struct request_queue *block_request_queue; //请求队列指针
 23 static struct gendisk *block_dev_disk; // gendisk结构体指针变量
 24 unsigned char block_dev_data[BLOCK_DEV_BYTES]; //模拟磁盘空间
 25 static void block_dev_do_request(struct request_queue *q) //该函数不能由驱动自己调用, 由系统调用. 系统认为到了该调用的时候就会调用
 26 {   //获取请求队列第一个IO请求
 27     struct request *req =blk_fetch_request(q);
 28     while ( req != NULL) {
 29         sector_t sector = blk_rq_pos(req);              //获取扇区第一个位置
 30         unsigned long nsector = blk_rq_cur_sectors(req);//获取扇区数目
 31         if ((sector + nsector)<<9 > BLOCK_DEV_BYTES)      //判断是否大于总容量
 32         {
 33             printk(KERN_ERR BLOCK_DISKNAME
 34                     ": bad request: block=%llu, count=%llu\n",
 35                     (unsigned long long)sector,
 36                     (unsigned long long)nsector);
 37                     __blk_end_request_all(req, -EIO);
 38             continue;
 39         }  
 40         //判断数据传输方向
 41         switch (rq_data_dir(req)) {
 42         case READ:
 43                 memcpy(req->buffer, block_dev_data + (sector<<9), nsector<<9);
 44                 break;
 45         case WRITE:
 46                 memcpy(block_dev_data + (sector<<9), req->buffer,  nsector<<9);
 47                 break;
 48         default: 
 49                 break;
 50         }
 51               //通知请求队列当前IO已经处理完毕
 52         if ( ! __blk_end_request_cur(req, 0) ) {
 53             req = blk_fetch_request(q); //继续读取下一个IO请求
 54         }
 55     }
 56 }
 57 static int block_dev_open (struct block_device *device, fmode_t mode)
 58 {
 59     printk("open %s\n", device->bd_disk->disk_name);
 60     return 0;
 61 }
 62 
 63 static int block_dev_release(struct gendisk *gendisk, fmode_t mode) //释放块设备
 64 {   
 65     printk("release %s\n", gendisk->disk_name);
 66     return 0;
 67 }
 68 
 69 struct block_device_operations block_dev_fops = {    //类似字符设备
 70         .owner    = THIS_MODULE,.open=block_dev_open, .release=block_dev_release
 71 };
 72 
 73 static int __init block_dev_init(void)
 74 {
 75     int ret;
 76     block_request_queue = blk_init_queue(block_dev_do_request, NULL);     //初始化请求队列
 77     if (!block_request_queue) {
 78         ret = -ENOMEM;
 79         goto err_init_queue;
 80     }
 81     
 82     block_dev_disk = alloc_disk(1); //分配磁盘
 83     if (!block_dev_disk) {
 84         ret = -ENOMEM;
 85         goto err_alloc_disk;
 86     }
 87     strcpy(block_dev_disk->disk_name, BLOCK_DISKNAME); //设备文件名
 88     block_dev_disk->major = BLOCK_DEVICEMAJOR;
 89     block_dev_disk->first_minor = 0;
 90     block_dev_disk->fops = &block_dev_fops;
 91     block_dev_disk->queue = block_request_queue;  //指定请求队列
 92     set_capacity(block_dev_disk, BLOCK_DEV_BYTES>>9); //设置磁盘容量
 93     add_disk(block_dev_disk); //添加磁盘
 94 
 95     return 0;
 96 
 97 err_alloc_disk:
 98     blk_cleanup_queue(block_request_queue);
 99     err_init_queue:
100     return ret;
101 }
102 
103 static void __exit block_dev_exit(void)
104 {
105     del_gendisk(block_dev_disk);//删除磁盘
106     put_disk(block_dev_disk);//gendisk引用次数减一
107     blk_cleanup_queue(block_request_queue);//清除请求队列
108 }
109 
110 module_init(block_dev_init);
111 module_exit(block_dev_exit);

 

块设备驱动

标签:switch   通知   exit   memcpy   gen   fcntl   自己   模拟   vma   

原文地址:https://www.cnblogs.com/debruyne/p/9431748.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!