UFFS文件系统与DFS关系

UFFS文件系统向上负责对象——DFS接口

我们在在应用程序中,对文件读写时,使用的都是open,read,wirte等函数,这些函数是dfs提供的。而dfs负责的是,根据不同的fd判断该文件是什么类型的设备,在调用相应类型的XXX_read函数。
uffs与dfs关系正事如此。当我们需要向NandFlash中的文件进行读写时,dfs会依据文件的属性,将具体read操作交给UFFS处理。
(注释:UFFS文件系统可以看成NandFlash的管理者,真正存储文件的载体是NandFlash这样的具体硬件设备,在下一篇文件中在进一步介绍这部分)。

首选让看一下UFFS系统加载过程中,与dfs相连的部分,系统初始化时 调用uffs_init(); 开始加载UFFS。主要代码如下:
通过UFFS向上层DFS接口看起,在UFFS初始化时,会把上上层负责的接口函数,同样以函数指针的存储方式,存储在dfs_uffs 结构中。上层dfs便可以通过这写接口访问UFFS,
在应用成执行 dfs->read(…) 如同调用 dfs_uffs_read(…)。

int uffs_init(void)
{
    rt_strncpy(dfs_uffs.name, "uffs", DFS_FS_NAME_MAX);

    dfs_uffs.mount  = dfs_uffs_mount;// 加载uffs
    dfs_uffs.unmount = dfs_uffs_unmount;// 移除uffs
    dfs_uffs.open   = dfs_uffs_open;// open
    dfs_uffs.close  = dfs_uffs_close;
    dfs_uffs.ioctl  = dfs_uffs_ioctl;
    dfs_uffs.read   = dfs_uffs_read;
    dfs_uffs.write  = dfs_uffs_write;
    dfs_uffs.lseek  = dfs_uffs_lseek;
    …
}

这有点类似于linux系统中的file_operations结构。
在uffs加载时,会把一下必要函数传递给dfs接口,也就是说,当dfs 执行read函数时,就会调用dfs_uffs_read。

而在uffs开始加载时。就会调用底层Nandflash初始化。UFFS真的是一个承上启下的东西。

int dfs_uffs_mount(struct dfs_filesystem* fs, unsigned long rwflag, const void* data)
{
    int result =uffs_init_filesystem(fs->path);//nandflash_init_filesystem(fs->path)
    if(result == 0)
    {
    return DFS_STATUS_OK;
     }
    return   DFS_STATUS_ENOENT;
}

接着看上边紧接着调用的: nandflash_init_filesystem

void nandflash_init_filesystem(char * path)
{

    uffs_MountTable *mtbl = &nand_mount_table[0];//rt_malloc(sizeof(uffs_MountTable)*2);
    struct uffs_ConfigSt cfg = {
        0,          // bc_caches - default
        0,          // page_buffers - default
        0,          // dirty_pages - default
        0,          // dirty_groups - default
        0,          // reserved_free_blocks - default
    };

  rt_memset((void*)&nand_device,0,sizeof( uffs_Device));
  rt_memset((void*)&flash_storage,0,sizeof(struct uffs_StorageAttrSt));

    //EMC_CTRL = 1;//enable,no map,normal mode
    if( NandInit() ==0)
    {
        rt_kprintf("No Flash found\r\n");
        return;
     }

    _ginitinfo =  Get_NandInitInfo();
    if(_ginitinfo == NULL)
    {
        rt_kprintf("No Flash Init Info \r\n");
        return;
    }

    rt_kprintf("nand info nandnbBlocks : %X  , %d\r\n",_ginitinfo->uNandID,_ginitinfo->uNandNbBlocks) ;
    /* setup nand storage attributes */
    setup_flash_storage(&flash_storage,_ginitinfo);

    while (mtbl->dev) {

        rt_memcpy(&mtbl->dev->cfg, &cfg, sizeof(struct uffs_ConfigSt));

#if CONFIG_USE_SYSTEM_MEMORY_ALLOCATOR > 0
        uffs_MemSetupSystemAllocator(&mtbl->dev->mem);
#endif
        mtbl->dev->Init = my_initDevice;
        mtbl->dev->Release = my_releaseDevice;
        mtbl->dev->attr = &flash_storage;

        uffs_RegisterMountTable(mtbl);
        mtbl++;
    }
    // 上边的代码都是获取一下必要信息,比如Flash的信息,这都都是结下了uffs加载时必定要用到的,根据不同的flash属性,加载时,申请的内存大小等等都是不同的。
    for (mtbl = &(nand_mount_table[0]); mtbl->mount != NULL; mtbl++) {
        // 这里才是重点 UFFS 加载的真正函数
        //nand_mount_table[] 存储着加载几块Nand设备,和起始地址范围
        uffs_Mount(mtbl->mount);
    }

}

uffs_Mount(mtbl->mount)这句话变开始建立真正的UFFS系统了。在这函数里面,会申请并初始化所以UFFS运行时所需要的内存,并且完成对底层NandFlash中,有效也的信息记录,把Flash中存储的文件,和文件夹链接关系都加载进入内存中,并且扫描Flash坏块等。在这里就不详细介绍了,后面我会对UFFS文件系统运行原理单独写一篇文章。在这里大家就先记住uffs_Mount 这个函数就行了~

二.UFFS与DFS调用关系
跑题了有点。回头看看UFFS与dfs个调用关系吧!
拿read函数举例,顶层read函数,终是如何调用到uffs_read()的。

1. read函数原型:

int read(int fd, char *buf, int   len)
{
    int result;
    struct dfs_fd* d;

    // 通过fd号,找到所对应的dfs文件对象,
    /* get the fd */
    d  = fd_get(fd);
    if (d == RT_NULL)
    {
        rt_set_errno(-RT_ERROR);
        return -1;
    }

    result = dfile_raw_read(d, buf, len);//重点
    if (result < 0)
    {
        rt_set_errno(result);
        fd_put(d);

        return -1;
    }

    /* release the ref-count of fd */
    fd_put(d);
    return result;
}

注释:理解d = fd_get(fd),上层根据不通的fd号,获取到所要操作的dfs对象,在文件open的时候 会创建这样一个对象。

int open(const char *file, int flags, int mode)
{
    int fd;
    struct dfs_fd* d;
    /* allocate a fd */
    fd = fd_new();
    ...
    dfile_raw_open(d, file, flags);
    ....
   return fd;
}

在看看dfs_fd结构

/* file descriptor */
struct dfs_fd
{
    char path[DFS_PATH_MAX + 1];/* Name (below mount point) */
    int type;                   /* Type (regular or socket) */
    int ref_count;              /* Descriptor reference count */

    struct dfs_filesystem* fs;  /* Resident file system */

    rt_uint32_t flags;          /* Descriptor flags */
    rt_size_t   size;           /* Size in bytes */
    rt_off_t    pos;            /* Current file position */

    void *data;                 /* Specific file system data */
};

这里面struct dfs_filesystem* fs 记录了将要read的文件,以何种方式处理。举个例子,比如一个dfs接口下面有两种文件系统,uffs和romfs。而应用层read(A.txt);这个“A”文件,是属于uffs还是romfs的文件,还有使用什么样的函数来完成具体的read任务。就是在这区分的。

2. dfile_raw_read函数

int dfile_raw_read(struct dfs_fd* fd, void *buf, rt_size_t len)
{
    struct dfs_filesystem* fs;
    int result = 0;

    if (fd == RT_NULL) return -DFS_STATUS_EINVAL;

    fs = (struct dfs_filesystem*) fd->fs;
    if (fs->ops->read == RT_NULL) return -DFS_STATUS_ENOSYS;
    // fs 就是刚才说的 struct dfs_filesystem* fs 结构
    if ( (result = fs->ops->read(fd, buf, len)) < 0 ) fd->flags |= DFS_F_EOF;

    return result;
}

fs->ops->read(fd, buf, len)),这里调用的指针函数->read是谁呢?

int uffs_init(void)
{
    rt_strncpy(dfs_uffs.name, "uffs", DFS_FS_NAME_MAX);
    dfs_uffs.read   = dfs_uffs_read;//就是它
    …
}

到此在dfs_uffs_read()函数中,获取dfs_fd->data,作为uffs_read()函数的参数,向下传递。
dfs_uffs.c 文件中源代码:

    int dfs_uffs_read(dfs_fd* file,  void* buf,  u32 len)
    {
        ….
        Int  fd = (int)(file->data);
        Int fd = (int)(file->data);
        uffs_read(fd, buf, len);
        ….
    }

来到了uffs的世界…
其他open,write等函数均类似如此。
dfs访问其他设备接口的过程也类似uffs
关于uffs与dfs的内容到此结束。
关于uffs_read是如何进行操作的,如何找在Flash中找到对应的文件,对文件读写,有待后文。。。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
提供的源码资源涵盖了安卓应用、小程序、Python应用和Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。
提供的源码资源涵盖了安卓应用、小程序、Python应用和Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。
提供的源码资源涵盖了安卓应用、小程序、Python应用和Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值