1. 程式人生 > >塊設備驅動

塊設備驅動

size_t lean any 是否 con rst unsigned int 文件名

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

塊設備驅動