嵌入式Linux驱动学习之路(二十二)用内存模拟磁盘

安装驱动后,可在/dev/目录下发现已经生成了相应的设备文件。

格式化设备:mkdosfs /dev/ramblock。

    挂载设备。

    读写设备 。

驱动程序代码:

/*************************************************************************
    > File Name: ramblock.c
    > Author: 
    > Mail: 
    > Created Time: 2016年11月05日 星期六 22时17分28秒
 ************************************************************************/
#include <linux/module.h>
#include <linux/errno.h>
#include <linux/interrupt.h>
#include <linux/mm.h>
#include <linux/fs.h>
#include <linux/kernel.h>
#include <linux/timer.h>
#include <linux/genhd.h>
#include <linux/hdreg.h>
#include <linux/ioport.h>
#include <linux/init.h>
#include <linux/wait.h>
#include <linux/blkdev.h>
#include <linux/blkpg.h>
#include <linux/delay.h>
#include <linux/io.h>

#include <asm/system.h>
#include <asm/uaccess.h>
#include <asm/dma.h>


#define RAMBLOCK_SIZE  (1024*1024)

struct gendisk *ramblock_disk;
static request_queue_t *ramblock_queue;

static DEFINE_SPINLOCK(ramblock_lock);

static int major;

static unsigned char *ramblock_buff;
static int ramblock_getgeo(struct block_device *bdev, struct hd_geometry *geo)
{
    /* 容量 = heads*sectors*cylinders*512 */
    geo->heads = 2;
    geo->sectors = 32;
    geo->cylinders = RAMBLOCK_SIZE/2/32/512;
    return 0;
}

static struct block_device_operations ramblock_fops = {
        .owner= THIS_MODULE,
        .getgeo = ramblock_getgeo,
};

static void do_ramblock_request(request_queue_t * q)
{
    struct request *req;
    static int r_cnt = 0;
    static int w_cnt = 0;
    while ((req = elv_next_request(q)) != NULL) 
    {
        /* 数据传输3要素 */
        /* 源/目的 */
        unsigned long offset = req->sector*512;

        /* 目的 */
        //req->buff
        
        /* 长度 */
        unsigned long len = req->current_nr_sectors * 512;

        if(rq_data_dir(req)==READ)
        {
            memcpy(req->buffer,ramblock_buff+offset, len);
            printk("read %d\n",r_cnt++);
        }
        else
        {
            memcpy(ramblock_buff+offset, req->buffer, len);
            printk("write %d\n",w_cnt++);
        }

        end_request(req, 1);/* wrap up, 0 = fail, 1 = success */
    }

}


static int ramblock_init(void)
{

    /* 分配一个gendisk结构体 */
    ramblock_disk = alloc_disk(16);  //次设备号个数=分区个数+1
    
    /* 设置 */
    /* 分配/设置队列:提供读写能力 */
    ramblock_queue = blk_init_queue(do_ramblock_request, &ramblock_lock);
    /* 设置其他属性 */
    major = register_blkdev(0,"ramblock");
    ramblock_disk->major = major;
    ramblock_disk->first_minor = 0;
    sprintf(ramblock_disk->disk_name, "ramblock");
    ramblock_disk->fops = &ramblock_fops;
    ramblock_disk->queue = ramblock_queue;
    set_capacity(ramblock_disk, RAMBLOCK_SIZE/512);

    /* 硬件相关 */
    ramblock_buff = kzalloc(RAMBLOCK_SIZE, GFP_KERNEL);
    /* 注册 */
    add_disk(ramblock_disk);


    return 0;
}


static void ramblock_exit(void)
{
    unregister_blkdev(major,"ramblock");
    del_gendisk(ramblock_disk);
    put_disk(ramblock_disk);
    blk_cleanup_queue(ramblock_queue);
    kfree(ramblock_buff);
}

module_init(ramblock_init);
module_exit(ramblock_exit);
MODULE_LICENSE("GPL");

 

 

sd

 

posted @ 2016-11-05 22:51  叶念西风  阅读(817)  评论(0编辑  收藏  举报
叶念西风 - 个人博客 & 电脑Run - 维修帮助软件教程安装