块设备驱动总结

知识储备:

          块设备驱动是基于扇区(sector)来访问底层物理磁盘,基于块(block)来访问上层文件系统。扇区一般是2的n次方大小,典型为512B,内核也要求块是2的n次方大小,且块大小通常为扇区大小的整数倍,并且块大小要小于页面大小,典型大小为512B、1K或4K。

     内存和NOR型闪存的基本存储单元是bit,用户可以随机访问任何一个bit的信息。NAND型闪存的基本存储单元是页(Page)(可以看到, NAND型闪存的页就类似硬盘的扇区,硬盘的一个扇区也为512字节)。每一页的有效容量是512字节的倍数。所谓的有效容量是指用于数据存储的部分,实际上还要加上16字节的校验信息,因此我们可以在闪存厂商的技术资料当中看到“(512+16)Byte”的表示方式。目前2Gb以下容量的NAND型闪存绝大多数是(512+16)字节的页面容量,2Gb以上容量的NAND型闪存则将页容量扩大到(2048+64)字节。
 NAND型闪存以块为单位进行擦除操作。闪存的写入操作必须在空白区域进行,如果目标区域已经有数据,必须先擦除后写入,因此擦除操作是闪存的基本操作。一般每个块包含32个512字节的页,容量16KB;而大容量闪存采用2KB页时,则每个块包含64个页,容量128KB。每颗NAND型闪存的I/O接口一般是8条,每条数据线每次传输(512+16)bit信息,8条就是(512+16)×8bit,也就是前面说的512字节。

     源代码:

#include<linux/init.h>
#include<linux/module.h>
#include<linux/genhd.h>
#include <linux/module.h>
#include <linux/errno.h>
#include <linux/interrupt.h>
#include <linux/mm.h>
#include <linux/fs.h>
#include <linux/kernel.h>
#include <linux/timer.h>
#include <linux/genhd.h>
#include <linux/hdreg.h>
#include <linux/ioport.h>
#include <linux/init.h>
#include <linux/wait.h>
#include <linux/blkdev.h>
#include <linux/blkpg.h>
#include <linux/delay.h>
#include <linux/io.h>
#include <linux/gfp.h>
#include <linux/slab.h>

#include <asm/system.h>
#include <asm/uaccess.h>
#include <asm/dma.h>
//#define   DEV_MAJOR  251
#define RAMDISK_SIZE (1024)
static struct gendisk * mydisk;
static struct request_queue *blkdev_queue;
static DEFINE_SPINLOCK(ramdisk_lock);
static unsigned char *ram_buff;
static int DEV_MAJOR;
static const struct block_device_operations rmbk_fops = {
	.owner	= THIS_MODULE,
};
static void ramblock_do_request(struct request_queue * q)
{
 
 struct request *req;
  printk("do:ramblock_do_request\n");
  req = blk_fetch_request(q);
  while (req){
	//源或目的
        unsigned long offset = blk_rq_pos(req)*512;
        
        //目的或源
        //req->buffer

       // 长度
        unsigned long len = blk_rq_cur_bytes(req);
        if(rq_data_dir(req) == READ)
		memcpy(req->buffer, ram_buff+offset, len);
        else
                memcpy(ram_buff+offset,req->buffer,len);
           
       // wrap up ,0 = success, -errno =fail       
         if(!__blk_end_request_cur(req,0))
		req = blk_fetch_request(q);
     }
}      



static int blkdev_init(void)
{
    printk("begin\n");
    // int ret;
  DEV_MAJOR = register_blkdev(DEV_MAJOR,  "vmdisk");/* 注册块设备 */
   /* 分配gendisk结构体*/
    mydisk  =  alloc_disk(1);
   
    
    blkdev_queue = blk_init_queue(ramblock_do_request,&ramdisk_lock);/* 为块设备准备一个请求队列 */
    mydisk->queue =  blkdev_queue;
  mydisk->major =  DEV_MAJOR;
  mydisk->first_minor  =  0;
  mydisk->fops =  &rmbk_fops;
  sprintf(mydisk->disk_name, "vmdisk");
  set_capacity(mydisk,  RAMDISK_SIZE);
  ram_buff = kzalloc(RAMDISK_SIZE, GFP_KERNEL);
  add_disk(mydisk);
  return 0;
}

static void blkdev_exit(void)
{   printk("quit\n");
    unregister_blkdev(DEV_MAJOR, "vmdisk");
    del_gendisk(mydisk);
    put_disk(mydisk);
    blk_cleanup_queue(blkdev_queue);
    kfree(ram_buff);
}
module_init(blkdev_init);
module_exit(blkdev_exit);
MODULE_LICENSE("GPL");

终端输入

FDISK的/ dev / ramdisk的进入块设备的设置

然后执行 

mkfs.vfat的/ dev / ramdisk的对分区进行格式化

接下来将其挂载到文件系统

执行命令

mount  /dev/块设备名 /ming

成功挂载


测试读写操作

LS> ming/123

cat 123



   


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值