塊設備是指只能以塊爲單位進行訪問的設備,塊大小通常是512個字節的整數倍。常見的塊設備包括硬件,SD卡,光盤等。node
l insmod simple-blk.kolinux
l ls /dev/simp_blkdev0算法
l mkfs.ext3 /dev/simp_blk0緩存
l mkdir –p /mnt/blk架構
l mount /dev/simp_blk0 /mnt/blkapp
l cp /etc/init.d/* /mnt/blk函數
l ls /mnt/blkfetch
l umount /mnt/blk設計
l ls /mnt/blkcode
(1) 系統架構-VFS
VFS是對各類具體文件系統的一種封裝,爲用戶程序訪問文件提供統一的接口。
(2) 系統架構-cache
當用戶發起文件訪問請求的時候,首先會到Disk Cache中尋找文件是否被緩存了,若是在cache中,則直接從cache中讀取。若是數據不在緩存中,就必需要到具體的文件系統中讀取數據了。
(3) Mapping Layer
l 首先肯定文件系統的block size,而後計算所請求的數據包含多少個block。
l 調用具體文件系統的函數來訪問文件的inode結構,肯定所請求的數據在磁盤上的地址。
(4) Generic Block Layer
Linux內核把把塊設備看做是由若干個扇區組成的數據空間。上層的讀寫請求在通用塊層被構形成一個或多個bio結構。
(5) I/O Scheduler Layer
I/O調度層負責採用某種算法(如:電梯調度算法)將I/O操做進行排序。
電梯調度算法的基本原則:若是電梯如今朝上運動,若是當前樓層的上方和下方都有請求,則先響應全部上方的請求,而後才向下響應下方的請求;若是電梯向下運動,則恰好相反。
(6)在塊系統架構的最底層,由塊設備驅動根據排序好的請求,對硬件進行數據訪問。
#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 major = 0;
static int sect_size = 512;
static int nsectors = 1024;
/*
* The internal representation of our device.
*/
struct blk_dev{
int size; /* Device size in sectors */
u8 *data; /* The data array */
struct request_queue *queue; /* The device request queue */
struct gendisk *gd; /* The gendisk structure */
};
struct blk_dev *dev;
/*
* Handle an I/O request, in sectors.
*/
static void blk_transfer(struct blk_dev *dev, unsigned long sector,
unsigned long nsect, char *buffer, int write)
{
unsigned long offset = sector*sect_size;
unsigned long nbytes = nsect*sect_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);
}
/*
* The simple form of the request function.
*/
static void blk_request(struct request_queue *q)
{
struct request *req;
req = blk_fetch_request(q);
while (req != NULL) {
struct blk_dev *dev = req->rq_disk->private_data;
blk_transfer(dev, blk_rq_pos(req), blk_rq_cur_sectors(req), req->buffer, rq_data_dir(req));
if(!__blk_end_request_cur(req, 0))
{
req = blk_fetch_request(q);
}
}
}
/*
* The device operations structure.
*/
static struct block_device_operations blk_ops = {
.owner = THIS_MODULE,
};
/*
* Set up our internal device.
*/
static void setup_device()
{
/*
* Get some memory.
*/
dev->size = nsectors*sect_size;
dev->data = vmalloc(dev->size);
if (dev->data == NULL) {
printk (KERN_NOTICE "vmalloc failure.\n");
return;
}
dev->queue = blk_init_queue(blk_request, NULL);
if (dev->queue == NULL)
goto out_vfree;
blk_queue_logical_block_size(dev->queue, sect_size);
dev->queue->queuedata = dev;
/*
* And the gendisk structure.
*/
dev->gd = alloc_disk(1);
if (! dev->gd) {
printk (KERN_NOTICE "alloc_disk failure\n");
goto out_vfree;
}
dev->gd->major = major;
dev->gd->first_minor = 0;
dev->gd->fops = &blk_ops;
dev->gd->queue = dev->queue;
dev->gd->private_data = dev;
sprintf (dev->gd->disk_name, "simp_blk%d", 0);
set_capacity(dev->gd, nsectors*(sect_size/sect_size));
add_disk(dev->gd);
return;
out_vfree:
if (dev->data)
vfree(dev->data);
}
static int __init blk_init(void)
{
/*
* Get registered.
*/
major = register_blkdev(major, "blk");
if (major <= 0) {
printk(KERN_WARNING "blk: unable to get major number\n");
return -EBUSY;
}
dev = kmalloc(sizeof(struct blk_dev), GFP_KERNEL);
if (dev == NULL)
goto out_unregister;
setup_device();
return 0;
out_unregister:
unregister_blkdev(major, "sbd");
return -ENOMEM;
}
static void blk_exit(void)
{
if (dev->gd) {
del_gendisk(dev->gd);
put_disk(dev->gd);
}
if (dev->queue)
blk_cleanup_queue(dev->queue);
if (dev->data)
vfree(dev->data);
unregister_blkdev(major, "blk");
kfree(dev);
}
module_init(blk_init);
module_exit(blk_exit);
FLASH在嵌入式系統中是必不可少的,它是bootloader、linux內核和文件系統的最佳載體。在Linux內核中引入了MTD子系統爲NORFLASH和NAND FLASH設備提供統一的接口,從而使得FLASH驅動的設計大爲簡化。