Android中的yaffs2文件系统与文件操作底层实现
2013-09-26 13:27
513 查看
1. yaffs2文件系统
yaffs2文件系统是用于NAND FLASH的文件系统. 由Android中增加的. 在原来的Linux2.2.26系统中没有这个文件系统.2. 应用层的文件操作
应用层的文件操作为fopen,fread, fwrite, 常用的文件操作函数. 下方操作我们以fread为例.struct file的定义在/kernel/include/linux/fs.h, 这个结构要记住.
struct file{ … const struct file_operations *f_op; … }
3. read的系统调用
SYSCALL_DEFINE3(read,unsigned int, fd, char __user *, buf, size_t, count) { struct file *file; ssize_t ret = -EBADF; int fput_needed; file = fget_light(fd, &fput_needed); if (file) { loff_t pos = file_pos_read(file); ret = vfs_read(file, buf, count,&pos); file_pos_write(file, pos); fput_light(file, fput_needed); } return ret; }
在系统调用中使用了函数vfs_read.此函数的实现在/kernel/fs/read_write.c中.
在vfs_read中, 有以下调用语句:
struct file *file;
if (file->f_op->read) ret = file->f_op->read(file,buf, count, pos); else ret = do_sync_read(file, buf, count,pos);
即, 如果file_operations类型的指针f_op有具体实现时, 使用具体实现; 否则直接使用do_sync_read.
4. yaffs2中的对file_operations实现
file_operations在/kernel/fs/yaffs2/yaffs_vfs.c下有相应实现.static conststruct file_operations yaffs_file_operations = { .read = do_sync_read, .write = do_sync_write, .aio_read = generic_file_aio_read, .aio_write = generic_file_aio_write, .mmap = generic_file_mmap, .flush = yaffs_file_flush, .fsync = yaffs_sync_object, .splice_read = generic_file_splice_read, .splice_write = generic_file_splice_write, .llseek = generic_file_llseek, };
在yaffs2中, 依然使用了do_sync_read. 但是其他如目录的管理等, 则是yaffs2的内容了.
在do_sync_read中, 有对yaffs2中的代码的调用, 即:
ret =filp->f_op->aio_read(&kiocb, &iov, 1, kiocb.ki_pos);
.aio_read =generic_file_aio_read, 说明依然不是在yaffs2中实现的.
5. mm中对generic_file_aio_read的实现
generic_file_aio_read的定义是在/kernel/mm/filemap.c中实现的.其中有调用do_generic_file_read(filp,ppos, &desc, file_read_actor);
do_generic_file_read是一个内容比较长的函数, 其中有page同步的调用. 大意是, 如果该文件的页面已在缓存中, 则直接读取; 否则, 先从设备中将该页面读取到缓存,然后再读取.
当page_ok时, 执行读取操作.
注意页面缓存这文件读取过程中的作用.
6. 复杂函数do_generic_file_read
这个复杂函数的执行过程如下:A. 根据address_space和索引去查找页面;
B. 如果没有找到页面, 则跳转到no_cached_page去进行页面缓存; 具体过程是, 先分配一个页面, 加入address_space链表, 然后error =mapping->a_ops->readpage(filp, page);然后执行PageUptodate.
C. 如果找到了, 执行PageUptodate检查;
D. 如果page_ok, 则调用actor函数指针, 将文件内容从页面缓存读取到用户缓冲区. 这里的actor函数指针的值由do_generic_file_read传入,实际上是file_read_actor.
intfile_read_actor(read_descriptor_t *desc, struct page *page, unsigned long offset, unsigned longsize) { char *kaddr; unsigned long left, count = desc->count; if (size > count) size = count; /* *Faults on the destination of a read are common, so do it before *taking the kmap. */ if(!fault_in_pages_writeable(desc->arg.buf, size)) { kaddr = kmap_atomic(page, KM_USER0); left =__copy_to_user_inatomic(desc->arg.buf, kaddr + offset, size); kunmap_atomic(kaddr, KM_USER0); if (left == 0) goto success; } /* Do it the slow way */ kaddr = kmap(page); left = __copy_to_user(desc->arg.buf, kaddr+ offset, size); kunmap(page); if (left) { size -= left; desc->error = -EFAULT; } success: desc->count = count - size; desc->written += size; desc->arg.buf += size; return size; }
7.与nandflash驱动的结合
与驱动的结合部分在address_space,它将设备中的内容读取到缓存中. 它的定义在yaffs2中.static structaddress_space_operations yaffs_file_address_operations = { .readpage= yaffs_readpage, .writepage= yaffs_writepage, .write_begin= yaffs_write_begin, .write_end= yaffs_write_end, }; static intyaffs_readpage(struct file *f, struct page *pg) { int ret; yaffs_trace(YAFFS_TRACE_OS,"yaffs_readpage"); ret = yaffs_readpage_unlock(f, pg); yaffs_trace(YAFFS_TRACE_OS,"yaffs_readpage done"); return ret; }
yaffs_readpage_unlock调用了yaffs_readpage_nolock,后者又调用了yaffs_file_rd.
yaffs_file_rd在/kernel/fs/yaffs2/yaffs_guts.c中实现.
yaffs_file_rd调用了yaffs_rd_data_obj, 后者调用了yaffs_rd_chunk_tags_nand.
yaffs_rd_chunk_tags_nand在/kernel/fs/yaffs2/yaffs_nand.c中实现.
其中有
if(dev->param.read_chunk_tags_fn) result = dev->param.read_chunk_tags_fn(dev, realigned_chunk, buffer, tags);
param类型为struct yaffs_param. 在yaffs_vfs.c中yaffs_internal_read_super函数中被赋值.
param->read_chunk_tags_fn = nandmtd2_read_chunk_tags;
nandmtd2_read_chunk_tags被定义在yaffs_mtdif2.c中.
通过struct mtd_info *mtd = yaffs_dev_to_mtd(dev);, nandmtd2_read_chunk_tags调用了如下语句:
retval = mtd->read(mtd, addr,dev->param.total_bytes_per_chunk, &dummy, data);
MTD(memory technology device内存技术设备)是用于访问memory设备(ROM、flash)的Linux的子系统。
所有组成MTD原始设备的Flash芯片必须是同类型(无论是interleave还是地址相连),在描述MTD原始设备数据结构中采用同一结构描述组成Flash芯片。每个MTD原始设备有一个mtd_info结构,其中的priv指针指向一个map_info结构,map_info结构中的fldrv_priv指向一个cfi_private结构,cfi_private结构的cfiq指针指向一个cfi_ident结构,chips指针指向一个flchip结构的数组。其中mtd_info、map_info和cfi_private结构用于描述MTD原始设备,因为组成MTD原始设备的NOR型Flash相同,cfi_ident结构用于描述Flash芯片信息;而flchip结构用于描述每个Flash芯片专有信息。
相关文章推荐
- android系统外部存储文件写操作的具体实现
- (转)linux sudo 重定向,实现只有系统管理员才有权限操作的文件中写入信息
- 【android开发】手写签名系统的设计与实现之实现文件夹以及文件列表显示(一)
- 使用HDFS API实现hadoop HDFS文件系统的基本操作
- 在Linux中实现大容量 NAND Flash的YAFFS2文件系统
- Android入门之文件系统操作(一)简单的文件浏览器
- Android 内核 yaffs2文件系统 不能包含
- Android入门之文件系统操作(一)简单的文件浏览器
- Android图形系统的底层实现
- 基于Blackfin处理器实现对硬盘FAT32文件系统的操作
- 修改底层文件,实现修改Android设备屏幕亮度和控制led灯
- 【android开发】手写签名系统的设计与实现之实现pdf文件上手写签名效果(五)---完
- Mac系统下利用ADB命令连接android手机并进行文件操作
- 【android开发】手写签名系统的设计与实现之实现解析pdf文件(二)
- Android入门之文件系统操作(二)文件操作相关指令
- 系统语言文件操作实现两个文档内容的复制
- Android的NDK开发(5)————Android JNI层实现文件的read、write与seek操作
- java实现对hdfs文件系统的上传,下载,删除,创建文件夹的操作演示
- NDK开发(五):Android JNI层实现文件的read、write与seek操作
- Android的NDK开发(5)————Android JNI层实现文件的read、write与seek操作