主 机: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.cdrivers\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 boundaryCommand (m for help): n
用rm命令手动删除该ramblock9.ko文件,然后再从服务器cp该文件到单板网络文件系统测试(正常):
Device Boot Start End Blocks Id System /dev/ramblock1 1 5 144 83 LinuxCommand (m for help):
总结:已经是第二次遇到这个问题了,文件并没有随着最新时间的相同文件的上传而被覆盖,相反旧文件覆盖了新文件或者没更新旧文件!这是为什么呢?
【源码】
ramblock9.c
1 /* 2 * 2019-01-10 3 * 目的: 分配一块内存,用这块内存做块设备模拟硬盘; 4 */ 5 #include6 #include 7 #include 8 #include 9 #include 10 #include 11 #include 12 #include 13 #include 14 #include 15 #include 16 #include 17 #include 18 #include 19 #include 20 #include 21 22 #include 23 #include 24 #include 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 clean11 rm -rf modules.order12 13 endif