天天看點

塊裝置原理分析--建立一個記憶體模拟磁盤的驅動執行個體

??????????????????????????????????????????????????????????????????ram???????????????????????????disk?????????????????????ramdisk????????????????????????????????????????????????????????????????????????????????????

????????????

    • ????????????????????????
    • ??????ramdisk??????????????????
      • 2.1 ???????????????
    • ??????ramdisk?????????

????????????????????????

?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????512B????????????????????????????????????????????????

塊裝置原理分析--建立一個記憶體模拟磁盤的驅動執行個體

???????????????????????????????????????????????????????????????????????????????????????????????????????????????=??????????????????????????????????????????????????????????????????????????????

塊裝置原理分析--建立一個記憶體模拟磁盤的驅動執行個體

??????????????????????????????????????? ????????????????????? ?? ??????(??????)??? ?? ??????????????? ?? ?????????????????????512???

?????????????????????????????????????????????????????????????????????????????????????????????request_queue???????????????????????????????????????????????????????????????????????????/???IO??????????????????????????????/????????????????????????????????????????????????????????????????????????????????????IO??????????????????????????????

???????????????ram????????????????????????????????????????????????????????????????????????????????????

??????ramdisk??????????????????

???????????????????????????3.10.0-123????????????????????????????????????ramdisk?????????????????????4MB???????????????ram??????

#include <linux/init.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/major.h>
#include <linux/blkdev.h>
#include <linux/bio.h>
#include <linux/highmem.h>
#include <linux/mutex.h>
#include <linux/radix-tree.h>
#include <linux/fs.h>
#include <linux/slab.h>
#include <asm/uaccess.h>
#include <linux/sizes.h>
#include <linux/kernel.h>
#include <linux/genhd.h>
#include <linux/hdreg.h>
#include <linux/blkpg.h>

#define DEVICE_NAME "ramdisk_test"
#define ram_size  SZ_4M
static DEFINE_SPINLOCK(ramdisk_lock);
struct gendisk *ramdisk;
static struct request_queue *disk_queue;
void *ram_addr;


static int ramdisk_getgeo(struct block_device *blk_dev, struct hd_geometry *geo)	
{
	geo->cylinders = 32; //?????????????????????
	geo->heads = 2; //????????????
	geo->sectors = ram_size/2/32/512;  //??????????????????????????????  
	printk(KERN_INFO "capacity %d\n", get_capacity(blk_dev->bd_disk)); //get_capacity(blk_dev->bd_disk)=8292
	return 0;

}
static struct kobject *ramdisk_probe(dev_t dev, int *part, void *data)
{

	printk(KERN_INFO "%s called\n", __FUNCTION__);
	*part = 0;
	return get_disk(ramdisk);
}

/*
?????????disk_queue?????????request????????????

*/

static void ramdisk_request(struct request_queue *q)
{
	struct request *req;
	printk(KERN_INFO "%s called\n", __FUNCTION__);

	req = blk_fetch_request(q);                        //???????????????disk_queue?????????request
	while (req) {
		unsigned long offset = blk_rq_pos(req) *512;  //?????????????????????????????????
		unsigned long len  = blk_rq_cur_bytes(req);  //request??????
		int err = 0;

		printk(KERN_INFO "%s offset:%d len %d\n", __FUNCTION__, offset, len);	
		if((u32)(offset+len) < ram_size)
		{
				if (rq_data_dir(req) == READ)  //???????????????
				{
					printk(KERN_INFO "%s read len %d\n", __FUNCTION__, len);
					memcpy(req->buffer, (char *)(ram_addr + offset), len);  //?????????(request??????buffer?????????????????????ramdisk????????????offset???????????????)
					
				}
				else
				{
					printk(KERN_INFO "%s write len %d\n", __FUNCTION__, len);
					memcpy((char *)(ram_addr + offset), req->buffer, len);  //?????????
					
				}
		}
		else
		{
			printk(KERN_INFO "fail %s offset:%d len %d\n", __FUNCTION__, offset, len);	
			
		}
	 
		
	done:
		if (!__blk_end_request_cur(req, err))  //end_request ??????
			req = blk_fetch_request(q);
	}
}

static const struct block_device_operations disk_fops =
{
	.owner		= THIS_MODULE,
	.getgeo     =  ramdisk_getgeo,
	//.open		= ramdisk_open,
	//.release	= ramdisk_release,
};

int major;
static int __init ramdisk_init(void)
{
    int ret;
	printk(KERN_INFO "%s called\n", __FUNCTION__);

    major = register_blkdev(0, DEVICE_NAME);   //???????????????????????????????????????

    disk_queue = blk_init_queue(ramdisk_request, &ramdisk_lock); //??????????????? request_queue????????????????????????ramdisk_request
	if (!disk_queue)
		goto out_queue;

	ramdisk = alloc_disk(1);  //????????????gendisk(??????????????????=?????????=1)
	ramdisk->queue = disk_queue; //???gendisk???????????????
    ramdisk->major = major;
    ramdisk->first_minor = 0;  //??????0---??????????????????????????????????????? 
    ramdisk->fops = &disk_fops;
    sprintf(ramdisk->disk_name, DEVICE_NAME);
	
	set_capacity(ramdisk, ram_size/512); //??????????????????????????????????????????
    add_disk(ramdisk);     //??????gendisk
	
    blk_register_region(MKDEV(major, 0), 1, THIS_MODULE,   //???????????????[0-1)
				ramdisk_probe, NULL, NULL);


	ram_addr = kzalloc(ram_size, GFP_KERNEL);

	if(!ram_addr)
	{
		kfree(ram_addr);
		goto out_queue;

	}
	
	printk(KERN_INFO "%s end\n", __FUNCTION__);
    return 0;
	

out_queue:
    put_disk(ramdisk);
out_disk:
    unregister_blkdev(major, DEVICE_NAME);
err:
    return -1;
}


static void __exit ramdisk_exit(void)
{
	
	blk_unregister_region(MKDEV(major, 0), 1);
	unregister_blkdev(major, DEVICE_NAME);
	put_disk(ramdisk);
   //del_gendisk(ramdisk);
    blk_cleanup_queue(disk_queue);

	kfree(ram_addr);
	return;
}


module_init(ramdisk_init);
module_exit(ramdisk_exit);
MODULE_LICENSE("GPL");

           

2.1 ???????????????

???????????????????????????????????????????????????

  1. ????????????????????????????????? register_blkdev
  2. ????????????????????????????????????????????????????????? blk_init_queue
  3. ??????gendisk??????????????????????????????????????????????????????fop?????? alloc_disk
  4. ????????????????????????????????? set_capacity
  5. ?????????????????? add_disk

?????????????????????4MB???????????????????????????????????????:

  1. ram_addr = kzalloc(ram_size, GFP_KERNEL); //??????4MB??????
  2. ??????????????????????????????ramdisk_request????????????????????????????????????

ramdisk_request???????????????????????????

  1. ???????????????????????????????????????request_queue????????????quest???
  2. ??????quest?????????????????????????????????????????????request?????????
  3. ?????????????????????????????????????????????ram???????????????memcpy ?????????req->buffer???ram?????????????????????

?????????????????????request_queue?????????????????????????????????????????????????????????????????????????????????????????????request???IO????????????????????????????????????

??????????????????:??????????????????request???????????????????????????if((u32)(offset+len) < ram_size)??????????????????????????????4M????????????????????????

塊裝置原理分析--建立一個記憶體模拟磁盤的驅動執行個體

???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????sync????????????????????????????????????????????????????????????????????????????????????????????????buffer???????????????ramdisk_request??????????????????????????????????????????request?????????

??????ramdisk?????????

  1. ??????????????????????????????????????????????????????/dev/ramdisk_test???
[[email??protected] mnt]# ls /dev/ramdisk_test  -l
brw-rw----. 1 root disk 252, 0 Feb  2 05:47 /dev/ramdisk_test
           
  1. ????????????????????????????????????????????????ramdisk_getgeo????????????????????????????????????????????????????????????????????????geo->heads ????????????/????????????geo->cylinders?????????????????????????????????geo->sectors??????
[[email??protected] ramdisk]# mkfs.ext4 /dev/ramdisk_test  #????????????ext4
mke2fs 1.42.9 (28-Dec-2013)
Filesystem label=
OS type: Linux
Block size=1024 (log=0)
Fragment size=1024 (log=0)
Stride=0 blocks, Stripe width=0 blocks
1024 inodes, 4096 blocks
204 blocks (4.98%) reserved for the super user
First data block=1
Maximum filesystem blocks=4194304
1 block group
8192 blocks per group, 8192 fragments per group
1024 inodes per group

Allocating group tables: done
Writing inode tables: done
Creating journal (1024 blocks): done
Writing superblocks and filesystem accounting information: done

           
[[email??protected] ramdisk]# mkfs.fat /dev/ramdisk_test  #???????????????fat
mkfs.fat 3.0.20 (12 Jun 2013)
           
????????????????????????ramdisk_getgeo????????????????????????????????????????????????????????????????????????????????????????????????
[[email??protected] ramdisk]# mkfs.fat /dev/ramdisk_test mkfs.fat 3.0.20
(12 Jun 2013) unable to get drive geometry, using default 255/63 ```
           
  1. fdisk????????????ramdisk???????????????????????????????????????????????????4MB???
[[email??protected] mnt]# fdisk -l /dev/ramdisk_test

Disk /dev/ramdisk_test: 4 MB, 4194304 bytes, 8192 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk label type: dos
Disk identifier: 0x00000000

            Device Boot      Start         End      Blocks   Id  System

           
  1. ??????????????????????????????????????????/mnt/?????????????????????
[[email??protected] /]# mount /dev/ramdisk_test /mnt/

[[email??protected] /]# mount |grep ramdisk
/dev/ramdisk_test on /mnt type vfat (rw,relatime,fmask=0022,dmask=0022,codepage=437,iocharset=ascii,shortname=mixed,errors=remount-ro)
[[email??protected] /]#