[国嵌攻略][147][简单块设备驱动设计]

Posted 盛夏夜

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[国嵌攻略][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!\n");
        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

 

以上是关于[国嵌攻略][147][简单块设备驱动设计]的主要内容,如果未能解决你的问题,请参考以下文章

[国嵌攻略][151][nandflash驱动程序设计]

[国嵌攻略][164][USB驱动程序设计]

[国嵌攻略][117][LED驱动程序设计]

[国嵌攻略][156][I2C自编设备驱动设计]

[国嵌攻略][158][SPI裸机驱动设计]

[国嵌攻略][177][网络安全传输系统模型设计]