• 块设备驱动1


      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
    ",
     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
    ", 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
    ", 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);
  • 相关阅读:
    Linux考试题附答案
    MariaDB数据库主从复制实现步骤
    LinuxCentos系统安装Mariadb过程记录
    LinuxCentos系统安装Nginx过程记录
    VMware虚拟机不能联网的解决办法
    Linux centos下设置定时备份任务
    如何修改本地hosts文件?
    mysql用户授权以及权限收回
    Ubuntu系统下完全卸载和安装Mysql
    C++之类和对象的使用(一)
  • 原文地址:https://www.cnblogs.com/debruyne/p/9431748.html
Copyright © 2020-2023  润新知