块设备驱动实验

25 篇文章 0 订阅
1 篇文章 0 订阅

一、理论知识

这里直接引用大佬的文章,讲解蛮清楚的。
块设备驱动程序设计(1)—块设备系统架构

二、程序编写

//参考 drivers/block/mg_disk.c    
//drivers/block/z2ram.c

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/blkdev.h>
#include <linux/hdreg.h>
#include <linux/ata.h>
#include <linux/interrupt.h>
#include <linux/delay.h>
#include <linux/platform_device.h>
#include <linux/gpio.h>
#include <linux/mg_disk.h>
#include <linux/slab.h>

#define RAMBLOCK_SIZE (1024*1024)

static DEFINE_SPINLOCK(ramblock_lock);

static struct gendisk *ramblock_disk;
static struct request_queue *ramblock_queue;
static int major;
static unsigned char *ramblock_buf;

//为了可以使用分区工具fdisk,内存可以假设成类似磁盘也有头 heads,柱面 cylinders,扇区 sectors
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 const struct block_device_operations ramblock_fops =
{
	.owner		= THIS_MODULE,
    .getgeo     = ramblock_getgeo,//几何信息
};

static void ramblock_request(struct request_queue *q)
{
	struct request *req;
    static int r_cnt = 0, w_cnt = 0;
 
	//从队列中取出要处理的一个请求
	req = blk_fetch_request(q);
	while (req != NULL) 
	{
        //源/目的
		unsigned long offset = blk_rq_pos(req) << 9;// * 512

        //目的/源
        void *buffer = bio_data(req->bio);
        //长度
		unsigned long len  = blk_rq_cur_bytes(req);
        
        if (rq_data_dir(req) == READ)
        {
 			printk("%s read %d\n", __FUNCTION__, ++r_cnt);           
            memcpy(buffer, offset + ramblock_buf, len);
        }            
        else
        {
            printk("%s write %d\n", __FUNCTION__, ++w_cnt);     
            memcpy(offset + ramblock_buf, buffer, len);
        }

		if (!__blk_end_request_cur(req, 0))
		{
			req = blk_fetch_request(q);
		}
	}
}

static int ramblock_init(void)
{
    /* 1. 分配一个gendisk结构体 */
    ramblock_disk = alloc_disk(16);/* 次设备号个数: 分区个数+1 */

	/* 2. 设置 */
	/* 2.1 分配/设置队列: 提供读写能力 */
    ramblock_queue = blk_init_queue(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)
{
    // blk_unregister_region(MKDEV(Z2RAM_MAJOR, 0), Z2MINOR_COUNT);
    unregister_blkdev(major, "ramblock");
    del_gendisk(ramblock_disk);
    put_disk(ramblock_disk);
    blk_cleanup_queue(ramblock_queue);

    kfree(ramblock_queue);
}


module_init(ramblock_init);
module_exit(ramblock_exit);
MODULE_LICENSE("GPL");

三、测试

/ # insmod ramblock.ko
ramblock_request read 1
 ramblock: unknown partition table
/ # ls -l /dev/ramblock
brw-------    1 0        0         254,   0 Jan  1 00:24 /dev/ramblock
/ # fdisk dev/ramblock  //分区工具
ramblock_request read 2
ramblock_request read 3
ramblock_request read 4
ramblock_request read 5
Device contains neither a valid DOS partition table, nor Sun, SGI, OSF or GPT 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.


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): 1
Last cylinder or +size or +sizeM or +sizeK (1-32, default 32): 5

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

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): 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.ramblock_request write 1

Calling ioctl() to re-read partition table
ramblock_request read 6
 ramblock: ramblock1 ramblock2
/ # ls dev/ramblock*
dev/ramblock   dev/ramblock1  dev/ramblock2
/ # ls dev/ramblock* -l
brw-------    1 0        0         254,   0 Jan  1 00:28 dev/ramblock
brw-------    1 0        0         254,   1 Jan  1 00:28 dev/ramblock1
brw-------    1 0        0         254,   2 Jan  1 00:28 dev/ramblock2
/ # mkdosfs dev/ramblock1
ramblock_request read 7
ramblock_request read 8
ramblock_request write 2
ramblock_request write 3
/ # mount /dev/ramblock1 /mnt
ramblock_request read 9
ramblock_request read 10
ramblock_request read 11
ramblock_request read 12
ramblock_request read 13
ramblock_request read 14
ramblock_request read 15
ramblock_request read 16
ramblock_request read 17
ramblock_request read 18
ramblock_request read 19
ramblock_request write 4
/ # ls /mnt
/ # umount /mnt/
ramblock_request write 5
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值