【驱动】第7课、块设备驱动之学习笔记

主   机:VMWare--Ubuntu-16.04.2-x64-100ask

开发板:Mini2440--256M NandFlash,   2M NorFlash,   64M SDRAM,   LCD-TD35;
    bootlorder:u-boot1.16,        Kernel:2.6.22.6;
编译器:arm-linux-gcc-3.4.5


目录

课堂笔记

编程

  一、驱动框架

  二、硬件相关的操作

  三、定义操作函数中,块设备的几何信息;

测试

源码


【课堂笔记】
框架:
app: open,read,write "1.txt"
--------------------------------------------- 文件的读写
文件系统: vfat, ext2, ext3, yaffs2, jffs2 (把文件的读写转换为扇区的读写)
-----------------ll_rw_block----------------- 扇区的读写
1. 把"读写"放入队列
2. 调用队列的处理函数(优化/调顺序/合并)
块设备驱动程序
---------------------------------------------
硬件: 硬盘,flash


【编程】
参考:
drivers\block\xd.c
drivers\block\z2ram.c
目的:分配一块内存,用这块内存作为块设备模拟硬盘;
一、驱动框架
1、分配一个gendisk结构体;
2、设置
2.1分配/设置一个队列:request_queue_t, 提供(块设备的)读写能力;
blk_init_queue();
2.2设置gendisk其他信息/属性(6项),比如:主设备号,次设备首号,名字,操作函数,容量,队列;
3、硬件操作:为块设备读写操作分配内存;
4、注册gendisk结构体;
add_disk(ramblock_disk);
5、操作函数所在fops结构体;

函数分配与回滚:
ramblock_disk = alloc_disk(16); 对应 put_disk(ramblock_disk); del_gendisk(ramblock_disk);
q = blk_init_queue(); 对应 blk_cleanup_queue(q);
register_blkdev(0, "ramblock"); 对应unregister_blkdev(major, "ramblock");

二、硬件相关的操作
1、硬件操作:为块设备读写操作分配内存;
2、在读写操作队列处理函数:do_xx_request()中,对读/写队列进行处理,然后结束队列;

三、定义操作函数中,块设备的几何信息;

  fops = {...     .getgeo = ramblock_getgeo,}

【测试】
1、块设备驱动,实验找不到mkdosfs命令?
答:开发板的文件系统缺少mkdosfs可执行文件!
2、硬件操作分配的内存 ramblock_buf = kzalloc(RAMBLOCK_SIZE, GFP_KERNEL),是为块设备读写操作分配的数据缓冲区,
还是为块设备本身分配的内存?
答:是为块设备本身分配的内存,为队列里读/写操作分配的数据缓冲区是struct request *req->buffer;该数据缓冲区貌
似是内核自己分配的,没有让驱动开发者手动分配!
3、网络文件系统上的ramblock9.ko没有删除直接用新文件上传覆盖时,测试(不正常):
Device Boot Start End Blocks Id System
/dev/ramblock1 1 5 288 83 Linux
Partition 1 has different physical/logical endings:
phys=(260, 1, 0) logical=(4, 1, 64)
Partition 1 does not end on cylinder boundary

Command (m for help): n

用rm命令手动删除该ramblock9.ko文件,然后再从服务器cp该文件到单板网络文件系统测试(正常):
Device Boot Start End Blocks Id System
/dev/ramblock1 1 5 144 83 Linux

Command (m for help):
总结:已经是第二次遇到这个问题了,文件并没有随着最新时间的相同文件的上传而被覆盖,相反旧文件覆盖了新文件或者没更新旧文件!
这是为什么呢?

 

 

 

【源码】

ramblock9.c

  1 /*
  2  * 2019-01-10
  3  * 目的: 分配一块内存,用这块内存做块设备模拟硬盘;
  4  */
  5 #include <linux/module.h>
  6 #include <linux/errno.h>
  7 #include <linux/interrupt.h>
  8 #include <linux/mm.h>
  9 #include <linux/fs.h>
 10 #include <linux/kernel.h>
 11 #include <linux/timer.h>
 12 #include <linux/genhd.h>
 13 #include <linux/hdreg.h>
 14 #include <linux/ioport.h>
 15 #include <linux/init.h>
 16 #include <linux/wait.h>
 17 #include <linux/blkdev.h>
 18 #include <linux/blkpg.h>
 19 #include <linux/delay.h>
 20 #include <linux/io.h>
 21 
 22 #include <asm/system.h>
 23 #include <asm/uaccess.h>
 24 #include <asm/dma.h>
 25 
 26 #define RAMBLOCK_SIZE (1024*1024)
 27 MODULE_LICENSE("GPL");
 28 
 29 static struct gendisk *ramblock_disk;
 30 static request_queue_t *ramblock_queue;
 31 static DEFINE_SPINLOCK(ramblock_lock);
 32 static int major;
 33 static unsigned char *ramblock_buf;
 34 
 35 /* 读写操作请求队列处理函数 */
 36 static void do_ramblock_request(request_queue_t *q)
 37 {
 38     struct request *req;
 39     while((req = elv_next_request(q)) != NULL)
 40     {
 41         /* 数据传输三要素: 源,长度,目的地 */
 42         unsigned long offset = req->sector*512;        /* 写入为目的地,读出为源 */
 43         unsigned long len = req->current_nr_sectors*512;
 44         if(rq_data_dir(req) == READ)
 45         {
 46             memcpy(req->buffer, ramblock_buf + offset, len);
 47         }
 48         else
 49         {
 50             memcpy(ramblock_buf + offset, req->buffer, len);
 51         }
 52 
 53         end_request(req, 1);
 54     }
 55 }
 56 
 57 static int ramblock_getgeo(struct block_device *bdev, struct hd_geometry *geo)
 58 {
 59     geo->heads = 2;
 60     geo->cylinders = 32;
 61     geo->sectors = RAMBLOCK_SIZE/2/32/512;
 62     return 0;
 63 }
 64 
 65 static struct block_device_operations ramblock_fops = {
 66     .owner = THIS_MODULE,
 67     .getgeo = ramblock_getgeo,
 68 };
 69 
 70 static int ramblock_init(void)
 71 {
 72     int err;
 73     /* 1.分配一个gendisk结构体 */
 74     ramblock_disk = alloc_disk(16);
 75     if(!ramblock_disk)
 76     {
 77         printk(KERN_ERR "Unable to allocate ramblock_disk gendisk!\n");
 78         err = -ENOMEM;
 79         goto err_fail1;
 80     }
 81     /* 2.配置该结构体 */
 82     /* 2.1分配/设置一个队列: 提供读写能力 */
 83     ramblock_queue = blk_init_queue(do_ramblock_request, &ramblock_lock);
 84     if(!ramblock_queue)
 85     {
 86         printk(KERN_ERR "Unable to prepare ramblock_queue request queue!\n");
 87         err = -ENOMEM;
 88         goto err_fail2;
 89     }
 90     /* 2.2其他属性: 主设备号,次设备首号,操作函数,队列,名字,容量等 */
 91     major = register_blkdev(0, "ramblock");
 92     if(!major)
 93     {
 94         printk(KERN_ERR "Unable to register ramblock block device!\n");
 95         err = -EBUSY;
 96         goto err_fail3;
 97     }
 98     ramblock_disk->major = major;
 99     ramblock_disk->first_minor = 0;
100     sprintf(ramblock_disk->disk_name, "ramblock");
101     ramblock_disk->fops = &ramblock_fops;
102     ramblock_disk->queue = ramblock_queue;
103     set_capacity(ramblock_disk, RAMBLOCK_SIZE/512);    //容量: 扇区数目;
104     /* 3.硬件相关的配置 */
105     ramblock_buf = kzalloc(RAMBLOCK_SIZE, GFP_KERNEL);
106     if(!ramblock_buf)
107     {
108         printk(KERN_ERR "Unable to allocate ramblock_buf buffer!\n");
109         err = -ENOMEM;
110         goto err_fail4;
111     }
112     /* 4.注册该结构体 */
113     add_disk(ramblock_disk);
114     return 0;
115 err_fail4:
116     kfree(ramblock_buf);
117 err_fail3:
118     unregister_blkdev(major, "ramblock");
119 err_fail2:
120     blk_cleanup_queue(ramblock_queue);
121 err_fail1:
122     put_disk(ramblock_disk);
123     del_gendisk(ramblock_disk);
124     return err;
125 }
126 
127 static void ramblock_exit(void)
128 {
129     unregister_blkdev(major, "ramblock");
130     blk_cleanup_queue(ramblock_queue);
131     put_disk(ramblock_disk);
132     del_gendisk(ramblock_disk);
133     kfree(ramblock_buf);
134 }
135 
136 module_init(ramblock_init);
137 module_exit(ramblock_exit);

 

Makefile:

 1 ifneq ($(KERNELRELEASE),)
 2     obj-m := ramblock9.o
 3 else
 4     KERN_DIR ?= /home/book/workbook/mini2440/systems/linux-2.6.22.6
 5 
 6     PWD = $(shell pwd)
 7 all:
 8     $(MAKE) -C $(KERN_DIR) M=$(PWD) modules
 9 clean:
10     $(MAKE) -C $(KERN_DIR) M=$(PWD) modules clean
11     rm -rf modules.order
12 
13 endif

 

posted @ 2019-01-10 20:47  大秦长剑  阅读(282)  评论(0编辑  收藏  举报