linuxのブロックデバイスドライバ
5503 ワード
:
app: open,read,write "1.txt"
---------------------------------------------
: vfat, ext2, ext3, yaffs2, jffs2 ( )
-----------------ll_rw_block-----------------
1. " "
2. ( / / )
---------------------------------------------
: ,flash
<LINUX >
ll_rw_block
for (i = 0; i < nr; i++) {
struct buffer_head *bh = bhs[i];
submit_bh(rw, bh);
struct bio *bio; // bh bio (block input/output)
submit_bio(rw, bio);
// : bio (request)
generic_make_request(bio);
__generic_make_request(bio);
request_queue_t *q = bdev_get_queue(bio->bi_bdev); //
// " "
ret = q->make_request_fn(q, bio);
// __make_request
__make_request
//
elv_merge(q, &req, bio);
// , bio
init_request_from_bio(req, bio);
//
add_request(q, req);
//
__generic_unplug_device(q);
// " "
q->request_fn(q);
?
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
3th,4th:
:
1. insmod ramblock.ko
2. : mkdosfs /dev/ramblock
3. : mount /dev/ramblock /tmp/
4. : cd /tmp, vi
5. cd /; umount /tmp/
6. cat /dev/ramblock > /mnt/ramblock.bin
7. PC ramblock.bin
sudo mount -o loop ramblock.bin /mnt
5th:
1. insmod ramblock.ko
2. ls /dev/ramblock*
3. fdisk /dev/ramblock
ドライバソース:
/* :
* 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 <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);
#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
", ++cnt);
while ((req = elv_next_request(q)) != NULL) {
/* : , , */
/* / : */
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
", ++r_cnt);
memcpy(req->buffer, ramblock_buf+offset, len);
}
else
{
//printk("do_ramblock_request write %d
", ++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 */
/* 2. */
/* 2.1 / : */
ramblock_queue = blk_init_queue(do_ramblock_request, &ramblock_lock);
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);
/* 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");