zoukankan      html  css  js  c++  java
  • [国嵌攻略][147][简单块设备驱动设计]

    头文件

    #include <linux/blkdev.h>

    #include <linux/bio.h>

    blkdev.c

    /********************************************************************
    *头文件
    *********************************************************************/
    #include <linux/init.h>
    #include <linux/module.h>
    #include <linux/errno.h>
    #include <linux/blkdev.h>
    #include <linux/bio.h>
    #include <linux/vmalloc.h>
    
    /********************************************************************
    *类型定义
    *********************************************************************/
    typedef struct blkdev{
        int size;                      //数据大小
        char *data;                    //数据内容
        struct request_queue *queue;   //请求队列
        struct gendisk *gd;            //磁盘结构
    }BLKDEV;
    
    /********************************************************************
    *全局变量
    *********************************************************************/
    static int major;   //主设备号
    BLKDEV *blkDev;     //设备结构
    
    /********************************************************************
    *请求队列
    *********************************************************************/
    //处理请求
    void blk_transfer(BLKDEV *blkDev, unsigned long sector,unsigned long number, char *buffer, int direction){
        //计算扇区位置
        unsigned long offset, nbytes;
        
        offset = sector * 512;   //设置扇区位置
        nbytes = number * 512;   //设置扇区大小
        
        //处理操作请求
        if(direction){   //是否写入请求
            memcpy(blkDev->data + offset, buffer, nbytes);   //向扇区写数据
        }else{           //是否读取请求
            memcpy(buffer, blkDev->data + offset, nbytes);   //从扇区读数据
        }
    }
    
    
    //处理队列
    void blk_request_queue(struct request_queue *q){
        //获取队列请求
        struct request *req;
        int isEnd;
        
        req = blk_fetch_request(q);
        while(req != NULL){   //是否存在请求
            //处理队列请求
            blk_transfer(blkDev, blk_rq_pos(req), blk_rq_cur_sectors(req), req->buffer, rq_data_dir(req));
            
            //获取队列请求
            isEnd = __blk_end_request_cur(req, 0);
            if(!isEnd){   //是否不是最后请求
                req = blk_fetch_request(q);
            }
        }
    }
    
    /********************************************************************
    *设备方法
    *********************************************************************/
    struct block_device_operations blk_ops = {
        .owner = THIS_MODULE
    };
    
    /********************************************************************
    *模块安装
    *********************************************************************/
    //安装模块
    static int iblk_init(void){
        //注册设备结构
        major = register_blkdev(0, "iblk");   //动态分配主设备号
        if(major <= 0){                       //如果分配失败返回
            printk("Register block device fail!
    ");
            return -EBUSY;
        }
        
        //分配设备结构
        blkDev = kmalloc(sizeof(BLKDEV), GFP_KERNEL);
        
        //分配设备空间
        blkDev->size = 1024 * 512;   //扇区大小=扇区数量*每块大小
        blkDev->data = vmalloc(blkDev->size);
        
        //分配请求队列
        blkDev->queue = blk_init_queue(blk_request_queue, NULL);
        
        //设置队列扇区
        blk_queue_logical_block_size(blkDev->queue, 512);
        
        //分配磁盘结构
        blkDev->gd = alloc_disk(1);
        
        //设置磁盘结构
        blkDev->gd->major = major;                     //主设备号
        blkDev->gd->first_minor = 0;                   //起始次设备号
        blkDev->gd->fops = &blk_ops;                   //设备方法
        blkDev->gd->queue = blkDev->queue;             //请求队列
        blkDev->gd->private_data = blkDev;             //私有成员
        sprintf(blkDev->gd->disk_name, "iblk%d", 0);   //设备文件名称
        set_capacity(blkDev->gd, 1024);                //扇区数量
        add_disk(blkDev->gd);                          //设置磁盘结构
        
        return 0;
    }
    
    //卸载模块
    static void iblk_exit(void){
        //释放磁盘结构
        del_gendisk(blkDev->gd);
        
        //释放请求队列
        blk_cleanup_queue(blkDev->queue);
        
        //释放结构空间
        vfree(blkDev->data);
        
        //释放设备结构
        kfree(blkDev);
        
        //注销设备结构
        unregister_blkdev(major, "iblk");
    }
    
    /********************************************************************
    *模块声明
    *********************************************************************/
    MODULE_LICENSE("GPL");
    MODULE_AUTHOR("D");
    MODULE_DESCRIPTION("");
    MODULE_VERSION("v1.0");
    
    module_init(iblk_init);
    module_exit(iblk_exit);

    Makefile

    ifneq ($(KERNELRELEASE),)
    
    obj-m := blkdev.o
    
    else
    
    KDIR := /lib/modules/2.6.32-279.el6.i686/build
    all:
        make -C $(KDIR) M=$(PWD) modules
    clean:
        @rm -f *.ko *.ko.unsigned *.mod.c *.mod.o *.o *.order *.symvers
    
    endif
  • 相关阅读:
    springboot集成thymeleaf中不能返回页面,只返回字符串
    MySql 视图
    边缘计算网关的作用
    什么是物联网网关?它有什么功能?
    RS232串口跟RS485串口有什么优缺点
    4G DTU在油田远程监控中的应用
    远程IO模块有何用途
    Spring5快乐教程(一)Spring概述
    vue水印-第一种方法
    js获取随机打乱的数组
  • 原文地址:https://www.cnblogs.com/d442130165/p/5279842.html
Copyright © 2011-2022 走看看