在linux系统中有一种文件系统很特殊,他便是ramdisk,当然完全的ramdisk已经由于其对内存容量的要求已经没人使用了,但是他的升级版本cramfs确实很瘦欢迎,尤其是在嵌入式设备中,当你想创建一个文件系统而又不想让人对其中的文件进行修改,那么cramfs便是很好的选择。在我的这个程序中,模仿ramdisk原理,从内存中开辟一块内存(8M),然后对其进行格式化,挂载使用。当然,这一切的任务是驱动完成的,所以本程序是一个块设备的驱动。好了废话不多说,请看程序(我已经添加了足够多的注释,基本山不用我再多解释了吧。。。。。)
/* * Sample disk driver for 2.6.35. */ //#include <linux/autoconf.h> #include <linux/module.h> #include <linux/moduleparam.h> #include <linux/init.h> #include <linux/sched.h> #include <linux/kernel.h> /* printk() */ #include <linux/slab.h> /* kmalloc() */ #include <linux/fs.h> /* everything... */ #include <linux/errno.h> /* error codes */ #include <linux/timer.h> #include <linux/types.h> /* size_t */ #include <linux/fcntl.h> /* O_ACCMODE */ #include <linux/hdreg.h> /* HDIO_GETGEO */ #include <linux/kdev_t.h> #include <linux/vmalloc.h> #include <linux/genhd.h> #include <linux/blkdev.h> //#include <linux/buffer_head.h> /* invalidate_bdev */ #include <linux/bio.h> MODULE_LICENSE("Dual BSD/GPL"); static int ramdisk_major = 0; module_param(ramdisk_major, int, 0); static int hardsect_size = 512; /*The size of a sector*/ module_param(hardsect_size, int, 0); static int nsectors = 8*1024*2; /* How big the drive is */ module_param(nsectors, int, 0); static int ndevices = 1; module_param(ndevices, int, 0); /* * The different "request modes" we can use. */ enum { RM_SIMPLE = 0, /* The extra-simple request function */ RM_FULL = 1, /* The full-blown version */ RM_NOQUEUE = 2, /* Use make_request */ }; //static int request_mode = RM_FULL; //static int request_mode = RM_SIMPLE; static int request_mode = RM_NOQUEUE; module_param(request_mode, int, 0); /* * Minor number and partition management. */ #define ramdisk_MINORS 16 //#define MINOR_SHIFT 4 //#define DEVNUM(kdevnum) (MINOR(kdev_t_to_nr(kdevnum)) >> MINOR_SHIFT /* * We can tweak our hardware sector size, but the kernel talks to us * in terms of small sectors, always. */ #define KERNEL_SECTOR_SIZE 512 /* * The internal representation of our device. */ struct ramdisk_dev { int size; /* Device size in bytes */ u8 *data; /* points to the space of device */ short users; /* How many users */ spinlock_t lock; /* For mutual exclusion */ struct request_queue *queue; /* The device request queue */ struct gendisk *gd; /* The gendisk structure */ }; static struct ramdisk_dev *Devices = NULL; /* * Handle an I/O request. * 瀹炵幇鎵囧尯鐨勮鍐? */ static void ramdisk_transfer(struct ramdisk_dev *dev, unsigned long sector, unsigned long nsect, char *buffer, int write) { unsigned long offset = sector*KERNEL_SECTOR_SIZE; unsigned long nbytes = nsect*KERNEL_SECTOR_SIZE; if ((offset + nbytes) > dev->size) { printk (KERN_NOTICE "Beyond-end write (%ld %ld)\n", offset, nbytes); return; } if (write) memcpy(dev->data + offset, buffer, nbytes); else memcpy(buffer, dev->data + offset, nbytes); } static void ramdisk_request(struct request_queue *q) { struct request *req; struct ramdisk_dev *dev; while ((req = blk_fetch_request(q)) != NULL) { dev= req->rq_disk->private_data; /* if (! blk_fs_request(req)) { printk (KERN_NOTICE "Skip non- ererefs request\n"); __blk_end_request_all(req, -EIO); printk("*** not blk_fs_request ***\n"); continue; } */ while ( 1 ) { ramdisk_transfer(dev, blk_rq_pos(req), blk_rq_cur_sectors(req), req->buffer, rq_data_dir(req)); if ( ! __blk_end_request_cur(req, 0) ) { break; } } } } /* * Transfer a single BIO. */ static int ramdisk_xfer_bio(struct ramdisk_dev *dev, struct bio *bio) { int i; struct bio_vec *bvec; sector_t sector = bio->bi_sector; /* Do each segment independently. */ bio_for_each_segment(bvec, bio, i) { char *buffer = __bio_kmap_atomic(bio, i, KM_USER0); ramdisk_transfer(dev, sector, bio_cur_bytes(bio)>>9 , buffer, bio_data_dir(bio) == WRITE); sector += bio_cur_bytes(bio)>>9; __bio_kunmap_atomic(bio, KM_USER0); } return 0; /* Always "succeed" */ } /* * Transfer a full request. */ static int ramdisk_xfer_request(struct ramdisk_dev *dev, struct request *req) { struct bio *bio; int nsect = 0; __rq_for_each_bio(bio, req) { ramdisk_xfer_bio(dev, bio); nsect += bio->bi_size/KERNEL_SECTOR_SIZE; } return nsect; } /* * Smarter request function that "handles clustering".*/ static void ramdisk_full_request(struct request_queue *q) { struct request *req; int nsect; struct ramdisk_dev *dev ; int i = 0; while ((req = blk_fetch_request(q)) != NULL) { dev = req->rq_disk->private_data; /* if (! blk_fs_request(req)) { printk (KERN_NOTICE "Skip non-fs request\n"); __blk_end_request_all(req, -EIO); continue; } */ nsect = ramdisk_xfer_request(dev, req); __blk_end_request(req, 0, (nsect<<9)); printk ("i = %d\n", ++i); } } //The direct make request version static void ramdisk_make_request(struct request_queue *q, struct bio *bio) { struct ramdisk_dev *dev = q->queuedata; int status; status = ramdisk_xfer_bio(dev, bio); bio_endio(bio, status); return; } /* * Open and close. */ static int ramdisk_open(struct block_device *bdev,fmode_t mode ) { struct ramdisk_dev *dev = bdev->bd_disk->private_data; spin_lock(&dev->lock); dev->users++; spin_unlock(&dev->lock); return 0; } static int ramdisk_release(struct gendisk *bd_disk, fmode_t mode) { struct ramdisk_dev *dev = bd_disk->private_data; spin_lock(&dev->lock); dev->users--; spin_unlock(&dev->lock); return 0; } static int ramdisk_getgeo(struct block_device *bdev, struct hd_geometry *geo) { unsigned long size; struct ramdisk_dev *pdev = bdev->bd_disk->private_data; size = pdev->size; geo->heads = 4; geo->sectors = 16; geo->start = 0; return 0; } /* * The device operations structure. */ static struct block_device_operations ramdisk_ops = { .owner = THIS_MODULE, .open = ramdisk_open, .release = ramdisk_release, .getgeo = ramdisk_getgeo, }; /* * Set up our internal device. */ static void setup_device(struct ramdisk_dev *dev, int which) { /* * Get some memory. */ memset (dev, 0, sizeof (struct ramdisk_dev)); dev->size = nsectors * hardsect_size; dev->data = vmalloc(dev->size); if (dev->data == NULL) { printk (KERN_NOTICE "vmalloc failure.\n"); return; } spin_lock_init(&dev->lock); /* * The I/O queue, depending on whether we are using our own * make_request function or not. */ switch (request_mode) { case RM_NOQUEUE: dev->queue = blk_alloc_queue(GFP_KERNEL); if (dev->queue == NULL) goto out_vfree; blk_queue_make_request(dev->queue, ramdisk_make_request); break; case RM_FULL: dev->queue = blk_init_queue(ramdisk_full_request, &dev->lock); if (dev->queue == NULL) goto out_vfree; break; case RM_SIMPLE: dev->queue = blk_init_queue(ramdisk_request, &dev->lock); if (dev->queue == NULL) goto out_vfree; break; default: printk(KERN_NOTICE "Bad request mode %d, using simple\n", request_mode); /* fall into.. */ } dev->queue->queuedata = dev; /* * And the gendisk structure. */ dev->gd = alloc_disk(ramdisk_MINORS); if (! dev->gd) { printk (KERN_NOTICE "alloc_disk failure\n"); goto out_vfree; } dev->gd->major = ramdisk_major; dev->gd->first_minor = which*ramdisk_MINORS; dev->gd->fops = &ramdisk_ops; dev->gd->queue = dev->queue; dev->gd->private_data = dev; snprintf (dev->gd->disk_name, 32, "ramdisk%c", which + 'a'); set_capacity(dev->gd, nsectors*(hardsect_size/KERNEL_SECTOR_SIZE)); add_disk(dev->gd); return; out_vfree: if (dev->data) vfree(dev->data); } static int __init ramdisk_init(void) { int i; /* * Get registered. */ ramdisk_major = register_blkdev(ramdisk_major, "ramdisk"); if (ramdisk_major <= 0) { printk(KERN_WARNING "ramdisk: unable to get major number\n"); return -EBUSY; } /* * Allocate the device array, and initialize each one. */ Devices = (struct ramdisk_dev *)kmalloc(ndevices*sizeof (struct ramdisk_dev), GFP_KERNEL); if (Devices == NULL) goto out_unregister; for (i = 0; i < ndevices; i++) setup_device(Devices + i, i); return 0; out_unregister: unregister_blkdev(ramdisk_major, "ramdisk"); return -ENOMEM; } static void ramdisk_exit(void) { int i; for (i = 0; i < ndevices; i++) { struct ramdisk_dev *dev = Devices + i; if (dev->gd) { del_gendisk(dev->gd); } if (dev->queue) { if (request_mode != RM_NOQUEUE) { blk_cleanup_queue(dev->queue); } } if (dev->data) vfree(dev->data); } unregister_blkdev(ramdisk_major, "ramdisk"); kfree(Devices); } module_init(ramdisk_init); module_exit(ramdisk_exit);
ifeq ($(KERNELRELEASE),) KERNELDIR ?= /lib/modules/$(shell uname -r)/build PWD := $(shell pwd) modules: $(MAKE) -C $(KERNELDIR) M=$(PWD) modules modules_install: $(MAKE) -C $(KERNELDIR) M=$(PWD) modules_install clean: rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c *.order *.symvers .tmp_versions .PHONY: modules modules_install clean else obj-m := ramdisk.o endif
然后使用fdisk命令进行分区设置,再挂载使用