memdisk驱动与块设备驱动框架
memdisk指的是以memory为基础,实现一个模拟的block device,这样在内存中虚拟出一块“磁盘”,用来在系统运行期间临时保存一些经常被访问到的文件。它产生的最初原因是因为在我们的SOC虚拟验证平台Zebu/Haps等上面并没有Nand/eMMC这类存储,没有分区去保存system.img/userdata.img/cache.img等来供Android系统启动。
块设备驱动框架
块设备是I/O设备中的一类,当我们的应用层对该设备读写时,是按扇区大小来读写数据的,若读写的数据小于扇区的大小,就会需要缓存区,可以随机读写设备的任意位置处的数据。
对于Linux块设备而言,只能以“块”为单位进行访问的设备,即一次性写入或者读出一个块整体,块是Linux定制的数据处理基本单位,大小通常由一个或者多个扇区组成,一般是512个字节的整数倍。
常见的块设备有Nand/eMMC存储、SD卡、光盘等.
从文件系统到磁盘
在Linux操作系统中,从用户态到磁盘的访问流程大致如下面框图所示:
各层API接口
分层 | API | Description | Notes |
---|---|---|---|
Libc | 没有访问权限 | 任何访问将产生域错误 | lalala |
Syscall | 没有访问权限 | 任何访问将产生域错误 | lalala |
VFS | 没有访问权限 | 任何访问将产生域错误 | lalala |
FS | 没有访问权限 | 任何访问将产生域错误 | lalala |
Generic Block Layer | void end_request(struct request *req, int uptodate) | 结束获取申请 | 当uptodate==0表示使用该申请读写扇区失败,uptodate==1表示成功 |
IO Scheduler | struct request *elv_next_request(request_queue_t *q) | 通过电梯算法获取申请队列中未完成的申请 | 获取成功返回一个request结构体,不成功返回NULL |
Block Driver | int register_blkdev(unsigned int major, const char *name) | 创建一个块设备 | 当major==0时表示动态创建,创建成功会返回一个主设备号 |
同上 | unregister_blkdev(unsigned int major, const char *name) | 卸载一个块设备 | 在出口函数中使用,major:主设备号,name:名称 |
同上 | struct gendisk *alloc_disk(int minors) | 分配一个gendisk结构 | minors为分区数,填1表示不分区 |
同上 | void del_gendisk(struct gendisk *disk) | 释放gendisk结构 | 在出口函数中使用,也就是不需要这个磁盘了 |
同上 | request_queue *blk_init_queue(request_fn_proc *rfn, spinlock_t *lock) | 分配一个request_queue请求队列 | 分配成功返回一个request_queue结构体 |
同上 | void blk_cleanup_queue(request_queue_t * q) | 清除内核中的request_queue请求队列 | 在出口函数中使用 |
同上 | static inline void set_capacity(struct gendisk *disk, sector_t size) | 设置gendisk结构体的扇区数(成员copacity) | size等于扇区数 |
同上 | void add_disk(struct gendisk *gd) | 向内核中注册gendisk结构体 | - |
同上 | void put_disk(struct gendisk *disk) | 注销内核中的gendisk结构体 | 在出口函数中使用 |
Hardware | 没有访问权限 | 任何访问将产生域错误 | lalala |
Android中磁盘mount过程
TODO...
uevent机制
memdisk的块设备驱动实现
memdisk的platform设备驱动实现
platform设备与块/字符设备
块/字符设备:根据访问设备的实际操作方式而言;
Platform设备:根据所在的总线类型而言,挂接在Linux虚拟的Platform总线上;
参考文档
@2018-04-02 10:40
Comments