标签: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