• 块设备驱动2


      1 #include <linux/module.h>
      2 #include <linux/blkdev.h>
      3 
      4 #define SIMP_BLKDEV_DISKNAME "simp_blkdev"          //块设备名
      5 #define SIMP_BLKDEV_DEVICEMAJOR COMPAQ_SMART2_MAJOR //主设备号
      6 #define SIMP_BLKDEV_BYTES (1*1024*1024)            // 块设备大小为50MB
      7 #define SECTOR_SIZE_SHIFT 9
      8 
      9 static struct gendisk *simp_blkdev_disk;// gendisk结构表示一个简单的磁盘设备
     10 static struct block_device_operations simp_blkdev_fops = { //块设备操作,gendisk的一个属性
     11     .owner = THIS_MODULE,
     12 };
     13 static struct request_queue *simp_blkdev_queue;//指向块设备请求队列的指针
     14 unsigned char simp_blkdev_data[SIMP_BLKDEV_BYTES];// 虚拟磁盘块设备的存储空间
     15 
     16 
     17 /******************************************************
     18 *
     19 *   磁盘块设备数据请求的处理函数
     20 *
     21 ******************************************************/
     22 static void simp_blkdev_do_request(struct request_queue *q){
     23     struct request *req;// 正在处理的请求队列中的请求
     24     struct bio *req_bio;// 当前请求的bio
     25     struct bio_vec *bvec;// 当前请求的bio的段(segment)链表
     26     char *disk_mem;      // 需要读/写的磁盘区域
     27     char *buffer;        // 磁盘块设备的请求在内存中的缓冲区
     28     int i = 0;
     29 
     30     while((req = blk_fetch_request(q)) != NULL){
     31         // 判断当前req是否合法
     32         if((blk_rq_pos(req)<<SECTOR_SIZE_SHIFT) + blk_rq_bytes(req) > SIMP_BLKDEV_BYTES){
     33             printk(KERN_ERR SIMP_BLKDEV_DISKNAME":bad request:block=%llu, count=%u
    ",(unsigned long long)blk_rq_pos(req),blk_rq_sectors(req));
     34             blk_end_request_all(req, -EIO);
     35             continue;
     36         }
     37         //获取需要操作的内存位置
     38         disk_mem = simp_blkdev_data + (blk_rq_pos(req) << SECTOR_SIZE_SHIFT);
     39         req_bio = req->bio;// 获取当前请求的bio
     40 
     41         switch (rq_data_dir(req)) {  //判断请求的类型
     42         case READ:
     43             // 遍历req请求的bio链表
     44             while(req_bio != NULL){
     45                 // for循环处理bio结构中的bio_vec结构体数组(bio_vec结构体数组代表一个完整的缓冲区)
     46                 for(i=0; i<req_bio->bi_vcnt; i++){
     47                     bvec = &(req_bio->bi_io_vec[i]);
     48                     buffer = kmap(bvec->bv_page) + bvec->bv_offset;
     49                     memcpy(buffer, disk_mem, bvec->bv_len);
     50                     kunmap(bvec->bv_page);
     51                     disk_mem += bvec->bv_len;
     52                 }
     53                 req_bio = req_bio->bi_next;
     54             }
     55             __blk_end_request_all(req, 0);
     56             break;
     57         case WRITE:
     58             while(req_bio != NULL){
     59                 for(i=0; i<req_bio->bi_vcnt; i++){
     60                     bvec = &(req_bio->bi_io_vec[i]);
     61                     buffer = kmap(bvec->bv_page) + bvec->bv_offset;
     62                     memcpy(disk_mem, buffer, bvec->bv_len);
     63                     kunmap(bvec->bv_page);
     64                     disk_mem += bvec->bv_len;
     65                 }
     66                 req_bio = req_bio->bi_next;
     67             }
     68             __blk_end_request_all(req, 0);
     69             break;
     70         default:
     71             /* No default because rq_data_dir(req) is 1 bit */
     72             break;
     73         }
     74     }
     75 }
     76 
     77 
     78 /******************************************************
     79 *
     80 *   模块的入口函数
     81 *
     82 ******************************************************/
     83 static int __init simp_blkdev_init(void){
     84     int ret;
     85 
     86     //1.添加设备之前,先申请设备的资源
     87     simp_blkdev_disk = alloc_disk(1);
     88     if(!simp_blkdev_disk){
     89         ret = -ENOMEM;
     90         goto err_alloc_disk;
     91     }
     92 
     93     //2.设置设备的有关属性(设备名,设备号,fops指针,请求队列,512B的扇区数)
     94     strcpy(simp_blkdev_disk->disk_name,SIMP_BLKDEV_DISKNAME);
     95     simp_blkdev_disk->major = SIMP_BLKDEV_DEVICEMAJOR;
     96     simp_blkdev_disk->first_minor = 0;
     97     simp_blkdev_disk->fops = &simp_blkdev_fops;
     98     // 将块设备请求处理函数的地址传入blk_init_queue函数,初始化一个请求队列
     99     simp_blkdev_queue = blk_init_queue(simp_blkdev_do_request, NULL);
    100     if(!simp_blkdev_queue){
    101         ret = -ENOMEM;
    102         goto err_init_queue;
    103     }
    104     simp_blkdev_disk->queue = simp_blkdev_queue;
    105     set_capacity(simp_blkdev_disk, SIMP_BLKDEV_BYTES>>9);
    106 
    107     //3.入口处添加磁盘块设备
    108     add_disk(simp_blkdev_disk);
    109     return 0;
    110 
    111     err_alloc_disk:
    112         return ret;
    113     err_init_queue:
    114         return ret;
    115 }
    116 
    117 
    118 /******************************************************
    119 *
    120 *   模块的出口函数
    121 *
    122 ******************************************************/
    123 static void __exit simp_blkdev_exit(void){
    124     del_gendisk(simp_blkdev_disk);// 释放磁盘块设备
    125     put_disk(simp_blkdev_disk);   // 释放申请的设备资源
    126     blk_cleanup_queue(simp_blkdev_queue);// 清除请求队列
    127 }
    128 
    129 
    130 module_init(simp_blkdev_init);// 声明模块的入口
    131 module_exit(simp_blkdev_exit);// 声明模块的出口

    Makefile文件:

     1 ifneq ($(KERNELRELEASE),) 
     2 MODULE_NAME := blk_ko
     3 OBJGMAC := simp_blkdev.o
     4 
     5 $(MODULE_NAME)-objs := $(OBJGMAC)
     6 obj-m := $(MODULE_NAME).o 
     7 
     8 else
     9 
    10 DRIVERDIR := $(shell pwd)
    11 KERNELDIR = /home/rayhe/share/rk3288_sdk/rk3288_rt
    12 
    13 all: 
    14     $(MAKE) -C $(KERNELDIR) M=$(DRIVERDIR) modules
    15 
    16 clean:
    17     rm -rf *.o  ./build/*.ko ./gmac/*.o  ./gmac/*.ko *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions modules.order Module.symvers
    18 endif

    参考网址:https://blog.csdn.net/cxy_chen/article/details/80998510

  • 相关阅读:
    JavaScript监控当前cpu使用状况
    JavaScript面向对象编程深入分析(1)
    学习Javascript闭包(Closure)
    JavaScript面向对象编程深入分析(3)
    JavaScript面向对象编程深入分析(2)
    浏览器的标准模式和怪异模式
    js实现简单网速测试方法
    浏览器的两种模式quirks mode 和strict mode
    详解Javascript 中的this指针
    virtualbox安装centos 6.4 server 网络连接问题
  • 原文地址:https://www.cnblogs.com/debruyne/p/9437138.html
Copyright © 2020-2023  润新知