#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)
static struct gendisk *grh_gendisk;
static struct request_queue *grh_queue;
static DEFINE_SPINLOCK(grh_spin_lock);
static int major;
static unsigned char *ramblock_buf;
//对队列中的请求进行处理的函数
static void grh_do_ramblock_req(struct request_queue *q){
struct request *req;
static int read_count=0, write_count=0;
unsigned long offset, count;
req = blk_fetch_request(q);
while (req) {
//真正的数据操作
offset = blk_rq_pos(req); //req对应的扇区的偏移量
count = blk_rq_cur_sectors(req); //req对应的数据传输量,以扇区为单位
offset <<= 9;
count <<= 9;
if(rq_data_dir(req) == READ){ //读操作
printk(KERN_EMERG"read count=%d\n", ++read_count);
memcpy(req->buffer, ramblock_buf+offset, count); /*从ramdisk把需要搬移的扇区数据移动到req的buffer里面*/
}
else{ //写操作
printk(KERN_EMERG"write count=%d\n", ++write_count);
memcpy(ramblock_buf+offset, req->buffer, count);
}
if (!__blk_end_request_cur(req, 0))
req = blk_fetch_request(q);
}
}
//获取柱面和扇区信息的函数,用于向分区工具提供参数
static int grh_getgeo(struct block_device *bdev, struct hd_geometry *geo){
geo->heads = 2; //假设2个面
geo->cylinders = 32; //假设32个柱面
geo->sectors = RAMBLOCK_SIZE/512/2/32; //算出扇区个数
return 0;
}
static struct block_device_operations grh_bdops = {
.owner = THIS_MODULE,
.getgeo = grh_getgeo,
};
static int ram_block_init(void){
//分配gendisk
grh_gendisk = alloc_disk(16); //分区个数为16
//设置gendisk
grh_queue = blk_init_queue(grh_do_ramblock_req, &grh_spin_lock); //创建操作队列
grh_gendisk->queue = grh_queue;
major = register_blkdev(0, "grh_ramblock");
grh_gendisk->major = major;
grh_gendisk->first_minor = 0;
sprintf(grh_gendisk->disk_name, "ramblock");
grh_gendisk->fops = &grh_bdops;
set_capacity(grh_gendisk, RAMBLOCK_SIZE/512); //设置块设备大小为1M
ramblock_buf = kzalloc(RAMBLOCK_SIZE, GFP_KERNEL);
if(NULL == ramblock_buf){
printk(KERN_EMERG"allocate buffer error!\n");
}
//注册gendisk
add_disk(grh_gendisk);
return 0;
}
static void ram_block_exit(void){
unregister_blkdev(major, "grh_ramblock");
del_gendisk(grh_gendisk);
put_disk(grh_gendisk);
blk_cleanup_queue(grh_queue);
kfree(ramblock_buf);
return;
}
module_init(ram_block_init);
module_exit(ram_block_exit);
MODULE_AUTHOR("GRH");
MODULE_VERSION("1.0");
MODULE_DESCRIPTION("RAM BLOCK DRIVER");
MODULE_LICENSE("GPL");
mini2440 入门块设备驱动(用RAM缓存模拟磁盘)代码记录(内核用的是2.6.32.2)
本文档详细记录了使用Linux内核2.6.32.2版本,通过RAM缓存来模拟块设备驱动的过程。代码涵盖了gendisk、request_queue的初始化,以及读写操作的处理。此外,还提供了获取磁盘几何信息的函数,以供分区工具使用。
摘要由CSDN通过智能技术生成