目的:把内存当作块设备使用
可以参考/driver/block/z2ram.c这个驱动程序
块设备驱动程序:
1. 分配gendisk: alloc_disk
2. 设置
2.1 分配/设置队列: request_queue_t // 它提供读写能力
blk_init_queue
2.2 设置gendisk其他信息 // 它提供属性: 比如容量
3. 注册: add_disk
代码如下
-
/* 参考:
-
* 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/mutex.h>
-
#include <linux/blkpg.h>
-
#include <linux/delay.h>
-
#include <linux/io.h>
-
#include <linux/gfp.h>
-
#include <linux/vmalloc.h>
-
-
#include <asm/uaccess.h>
-
#include <asm/dma.h>
-
-
#define RAMBLOCK_SIZE 0x100000
-
-
static int major;
-
static struct gendisk *ramblock_disk;
-
static struct request_queue *ramblock_queue;
-
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;
-
-
req = blk_fetch_request(q);
-
while ( req ) {
-
/* 数据传输3要素: 源,目的,长度 */
-
/* 源/目的 */
-
unsigned long offset = blk_rq_pos(req) * 512;
-
-
/* 目的/源: req->buffer */
-
-
/* 长度 */
-
unsigned long len = blk_rq_cur_bytes(req);
-
-
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);
-
}
-
-
if (!__blk_end_request_cur(req, 0))
-
req = blk_fetch_request(q);
-
}
-
}
-
-
static int ramblock_init(void)
-
{
-
/* 0. 注册块设备,register_blkdev : cat /proc/devices */
-
major = register_blkdev(0, "ramblock");
-
-
/* 1. 分配gendisk */
-
ramblock_disk = alloc_disk(2); /* 次设备号个数:分区个数2 */
-
-
/* 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) */
-
ramblock_disk->fops = &ramblock_fops;
-
set_capacity(ramblock_disk, RAMBLOCK_SIZE / 512);//设置容量,以扇区为单位,对于内存,永远认为扇区容量为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");
测试:
在开发板上:
1. 加载驱动: insmod ramblock.ko
2. 格式化: mkdosfs /dev/ramblock
3. 挂载到/tmp目录: mount /dev/ramblock /tmp/
4. 读写文件: cd /tmp, 在里面vi文件,如1.txt
5. 解除挂载:cd /; umount /tmp/
6. 重新
挂载到/tmp目录: mount /dev/ramblock /tmp/,发现刚刚创建的文件依然存在
7.把
ramblock里的内容导出为二进制文件: cat /dev/ramblock > /mnt/ramblock.bin
8. 在PC上查看ramblock.bin:sudo mount -o loop ramblock.bin /mnt,在ubuntu的/mnt下看到了在开发板上创建的那个文件
9.
给ramblock分区:fdisk /dev/ramblock,根据帮助提示完成分区
10.查看分区: ls /dev/ramblock* -l ,发现有了新分区,次设备号0代表整个ramblock
阅读(1420) | 评论(0) | 转发(0) |