vi ramblock.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 <asm/system.h>
#include <asm/uaccess.h>
#include <asm/dma.h>
static struct gendisk *ramblock_disk;
static request_queue_t *ramblock_queue;
static int major;
static DEFINE_SPINLOCK(ramblock_lock);
static struct block_device_operations ramblock_fops = {
.owner = THIS_MODULE,
};
#define RAMBLOCK_SIZE (1024*1024)
static void do_ramblock_request(request_queue_t * q)
{
static int cnt = 0;
struct request *req;
printk("do_ramblock_request %d\n",++cnt);
while ((req = elv_next_request(q)) != NULL) {
end_request(req, 1);
}
}
static int ramblock_init(void)
{
ramblock_disk = alloc_disk(16);
ramblock_queue = blk_init_queue(do_ramblock_request, &ramblock_lock);
ramblock_disk->queue = ramblock_queue;
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;
set_capacity(ramblock_disk, RAMBLOCK_SIZE/512);//p->heads * p->cylinders * p->sectors);
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");
测试驱动程序:
# insmod ramblock.ko
ramblock:do_ramblock_request 1
unknown partition table
# ls /dev/ramblock -l
brw-rw---- 1 0 0 254, 0 Jan 1 00:00 /dev /ramblock
# cat /proc/devices
Block devices:
254 ramblock
vi ramblock.c(增加读写)
static unsigned char *ramblock_buf;
static void do_ramblock_request(request_queue_t * q)
{
static int 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;
unsigned long len = req->current_nr_sectors * 512;
if (rq_data_dir(req) == READ)
memcpy(req->buffer, ramblock_buf+offset, len);
else
memcpy(ramblock_buf+offset, req->buffer, len);
end_request(req, 1);
}
}
static int ramblock_init(void)
{
ramblock_disk = alloc_disk(16);
ramblock_queue = blk_init_queue(do_ramblock_request, &ramblock_lock);
ramblock_disk->queue = ramblock_queue;
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;
set_capacity(ramblock_disk, RAMBLOCK_SIZE/512);//p->heads * p->cylinders * p->sectors);
ramblock_buf = 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_buf);
}
测试驱动程序:
# insmod ramblock.ko
ramblock:do_ramblock_request 1
unknown partition table
# mkdosfs /dev/ramblock
mkdosfs 2.11 (12 Mar 2005)
do_ramblock_request 2
do_ramblock_request 3
unable to get drive geometry, using ddo_ramblock_request 4
# mount /dev/ramblock /tmp/
do_ramblock_request 5
do_ramblock_request 6
# cd /tmp
# vi hello.txt
# ls
hello.txt # cd /
# umount /tmp do_ramblock_request 45
# mount /dev/ramblock /tmp/
do_ramblock_request 46
do_ramblock_request 47
do_ramblock_request 48
# cd /tmp
# ls
hello.txt
# fdisk /dev/ramblock
do_ramblock_request 85
Unknown value(s) for: cylinders (settable in the extra functions menu)
Command (m for help):
vi ramblock.c(增加分区)
static int ramblock_getgeo(struct block_device *bdev, struct hd_geometry *geo)
{
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,
};
测试驱动程序:
# insmod ramblock.ko
ramblock:do_ramblock_request 1
unknown partition table
# ls /dev/ramblock -l
brw-rw---- 1 0 0 254, 0 Jan 1 00:00 /dev/ramblock
# fdisk /dev/ramblock
do_ramblock_request 2
Device contains neither a valid DOS partition table, nor Sun, SGI or OS F disklabel
Building a new DOS disklabel. Changes will remain in memory only,
until you decide to write them. After that the previous content
won't be recoverable.
Warning: invalid flag 0x00,0x00 of partition table 4 will be corrected by w(rite)
Command (m for help): m
Command Action
a toggle a bootable flag
b edit bsd disklabel
c toggle the dos compatibility flag
d delete a partition
l list known partition types
n add a new partition
o create a new empty DOS partition table
p print the partition table
q quit without saving changes
s create a new empty Sun disklabel
t change a partition's system id
u change display/entry units
v verify the partition table
w write table to disk and exit
x extra functionality (experts only)
Command (m for help): n
Command action
e extended
p primary partition (1-4)
p
Partition number (1-4): 1
First cylinder (1-32, default 1): Using default value 1
Last cylinder or +size or +sizeM or +sizeK (1-32, default 32): 5
Command (m for help): n
Command action
e extended
p primary partition (1-4)
p
Partition number (1-4): 2
First cylinder (6-32, default 6): 6
Last cylinder or +size or +sizeM or +sizeK (6-32, default 32): Using de fault value 32
Command (m for help): p
Disk /dev/ramblock: 1 MB, 1048576 bytes
2 heads, 32 sectors/track, 32 cylinders
Units = cylinders of 64 * 512 = 32768 bytes
Device Boot Start End Blocks Id System
/dev/ramblock1 1 5 144 83 Linux
/dev/ramblock2 6 32 864 83 Linux
Command (m for help): w
The partition table has been altered!
do_ramblock_request 3
ramblock:do_ramblock_request 4
ramblock1 ramblock2
Calling ioctl() to re-read partition table
# ls /dev/ramblock* -l
brw-rw---- 1 0 0 254, 0 Jan 1 00:05 /dev/ramblock
brw-rw---- 1 0 0 254, 1 Jan 1 00:05 /dev/ramblock1
brw-rw---- 1 0 0 254, 2 Jan 1 00:05 /dev/ramblock2
#