块设备是指只能以块为单位进行访问的设备,块大小一般是512个字节的整数倍。常见的块设备包括SD卡。
VFS是对各种具体文件系统的一种封装,为用户程序访问文件提供统一的接口。
当用户发起文件访问请求的时候,首先会到Disk Cache中寻找文件是否被缓存了,如果在cache中,则直接从cache中读取。如果数据不在缓存中,就必须要到具体的文件系统中读取数据了。
#include<linux/module.h>
#include<linux/init.h>
#include<linux/errno.h>
#include<linux/blkdev.h>
#include<linux/bio.h>
static int major =0;
static int sect_size = 512;
static int nsectors = 1024;
struct blk_dev{
int size;
u8 *data;
struct request_queue *queue;
struct gendisk *gd;
};
struct blk_dev *dev;
//操作函数集
static struct block_device_operations blk_ops ={
.owner = THIS_MODULE,
};
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(write)
memcpy(dev->data+offset,buffer,nbytes);将用户的数据写入buffer
else
memcpy(buffer,dev->data+offset,nbytes);
}
static void blk_request(struct request_queue *q)
{
struct request *req;
req = blk_fetch_request(q);
while(req!=NULL)
{
//处理该请求
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);
}
}
void setup_device()
{ dev->size = nsectors*sect_size;//字节大小
dev->data = vmalloc(dev->size);
dev->queue = blk_init_queue(blk_request,NULL);//初始化队列,通过调用blk_request完成用户的请求
blk_queue_logical_block_size(dev->queue,sect_size);
dev->gd=alloc_disk(1);//初始化gendisk结构
dev->gd->major = 0;
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);
add_disk(dev->gd);//将该块设备添加到内核
}
static int blk_init(void)
{
major=register_blkdev(0,"blk");//注册块设备
if(major<=0)
{
printk("register blk dev fail\n");
return -EBUSY;
}
dev = kmalloc(sizeof(struct blk_dev),GFP_KERNEL);//为块设备的分配描述结构
setup_device();
return 0;
}
static void blk_exit(void)
{
del_gendisk(dev->gd);
put_disk(dev->gd);
blk_cleanup_queue(dev->queue);
vfree(dev->data);
unregister_blkdev(major,"blk");
kfree(dev);
}
module_init(blk_init);
module_exit(blk_exit);
MTD系统架构
在Linux内核中引入了MTD子系统为NOR FLASH和NAND FLASH设备提供统一的接口,从而使得FLASH驱动的设计大为简化。
Yaffs2文件系统