微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > 嵌入式设计 > 块设备驱动程序的编写驱动之用内存模拟磁盘

块设备驱动程序的编写驱动之用内存模拟磁盘

时间:11-21 来源:互联网 点击:
// 参考:

// drivers\block\xd.c

// drivers\block\z2ram.c

#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

#include

#include

static struct gendisk *ramblock_disk;

static request_queue_t *ramblock_queue;

static int major;

static DEFINE_SPINLOCK(ramblock_lock);

#define RAMBLOCK_SIZE (1024*1024)

static unsigned char *ramblock_buf;

static int ramblock_getgeo(struct block_device *bdev, struct hd_geometry *geo)

{

// 容量=heads*cylinders*sectors*512

geo->heads = 2;

geo->cylinders = 32;

geo->sectors = 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)

{

static int r_cnt = 0;

static int w_cnt = 0;

struct request *req;

//printk("do_ramblock_request %d\n", ++cnt);

while ((req = elv_next_request(q)) != NULL) {

// 数据传输三要素: 源,目的,长度

// 源/目的:

unsigned long offset = req->sector * 512;

// 目的/源: (写的时候buffer是源,读的时候buffer是目的,从扇区里读出来放在buffer里)

// req->buffer

// 长度:

unsigned long len = req->current_nr_sectors * 512;

if (rq_data_dir(req) == READ)

{

//如果是操作硬盘的话在这个位置放置读取硬盘的函数就可以了

//printk("do_ramblock_request read %d\n", ++r_cnt);

memcpy(req->buffer, ramblock_buf+offset, len);

}

else

{

//如果是操作硬盘的话在这个位置放置写硬盘的函数就可以了

//printk("do_ramblock_request write %d\n", ++w_cnt);

memcpy(ramblock_buf+offset, req->buffer, len);

}

end_request(req, 1);

}

}

static int ramblock_init(void)

{

// 1. 分配一个gendisk结构体

ramblock_disk = alloc_disk(16); // 次设备号个数: 分区个数+1 ,表示有15个分区

// 2. 设置

// 2.1 分配/设置队列: 提供读写能力

ramblock_queue = blk_init_queue(do_ramblock_request, &ramblock_lock);//do_ramblock_request队列处理函数

ramblock_disk->queue = ramblock_queue;

// 2.2 设置其他属性: 比如容量

major = register_blkdev(0, "ramblock"); // cat /proc/devices

ramblock_disk->major = major;

ramblock_disk->first_minor = 0;

sprintf(ramblock_disk->disk_name, "ramblock");

ramblock_disk->fops = &ramblock_fops;

set_capacity(ramblock_disk, RAMBLOCK_SIZE / 512); //在内核里面对于文件系统那一层,认为 //扇区永远是512字节,即为扇区数

//块设备的操作是以扇区为单位的。

// 3. 硬件相关操作

ramblock_buf = kzalloc(RAMBLOCK_SIZE, GFP_KERNEL);

// 4. 注册

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_buf);

}

module_init(ramblock_init);

module_exit(ramblock_exit);

MODULE_LICENSE("GPL");

==============================================================

框架:

app: open,read,write "1.txt"

--------------------------------------------- 文件的读写

文件系统: vfat, ext2, ext3, yaffs2, jffs2 (把文件的读写转换为扇区的读写)

-----------------ll_rw_block----------------- 扇区的读写

1. 不像字符设备那样提供读写函数,而是把"读写"放入队列

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top