ramblock.c源码:
// 参考drivers/block/xd.c,z2ram.c
#include "linux/major.h"
#include "linux/vmalloc.h"
#include "linux/init.h"
#include "linux/module.h"
#include "linux/blkdev.h"
#include "linux/bitops.h"
#include "linux/hdreg.h"
#define RAMBLOCK_SIZE 0x100000
static struct gendisk *ramblock_disk;
static struct request_queue *ramblock_queue;
static int major;
static unsigned char *ramblock_buf;
static DEFINE_SPINLOCK(ramblock_lock);
static int ramblock_getgeo(struct block_device *dev, struct hd_geometry *geo)
{
// 容量 = heads * cylinders * sectors *512
geo->heads = 2;
geo->cylinders = 128;
geo->sectors = RAMBLOCK_SIZE / 2 / 128 / 512;
return 0;
}
static struct block_device_operations ramblock_fops =
{
.owner = THIS_MODULE,
.getgeo = ramblock_getgeo,
};
static void do_ramblock_request(struct request_queue *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)
{
// 数据传输3要素: 源,目的,长度
// 源/目的
unsigned long offset = req->sector * 512;
// 目的/源: 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); // 1 - 成功
}
}
static int ramblock_init(void)
{
// 0. register_blkdev : cat /proc/devices
major = register_blkdev(0, "ramblock");
// 1. 分配gendisk
ramblock_disk = alloc_disk(2); // 0-整个磁盘, 1-第1个分区
// 2. 设置
// 2.1 设置队列: 提供读写的能力
ramblock_queue = blk_init_queue(do_ramblock_request, &ramblock_lock);
ramblock_disk->queue = ramblock_queue;
// 2.2 设置属性: 比如容量,主设备号,第1个次设备号,操作函数等
ramblock_disk->major = major;
ramblock_disk->first_minor = 0; // (major,0),(major,1),...,(major,15)
ramblock_disk->fops = &ramblock_fops;
set_capacity(ramblock_disk, RAMBLOCK_SIZE / 512);
sprintf(ramblock_disk->disk_name, "ramblock");
// 3. 硬件相关操作
ramblock_buf = vmalloc(RAMBLOCK_SIZE);
// 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);
}
module_init(ramblock_init);
module_exit(ramblock_exit);
MODULE_LICENSE("GPL");
=====================================================================
Makefile文件:
KERN_DIR = /home/linux-3.0.1
all:
make -C $(KERN_DIR) M=`pwd` modules
clean:
make -C $(KERN_DIR) M=`pwd` modules clean
rm -rf modules.order
obj-m += ramblock.o
=====================================================================
测试详情参考:JZ2440块设备驱动程序的编写驱动之用内存模拟磁盘
『本文转载自网络,版权归原作者所有,如有侵权请联系删除』