当前位置:   article > 正文

RT-Thread文件系统(dfs)浅析_使用posix读写sd卡

使用posix读写sd卡

概述

RT-Thread–很好的一款rtos,各种组件齐全。本文旨在记录下对RT-Thread的文件系统初识。进而引申思考linux下的vfs是否也类似于此。

缘起

近来自忖采用sd卡作为大量数据的载体,以便在没有网络支持的场景下,保存嵌入式系统运行的记录及数据。RT-Thread下正好集成了sd卡驱动,又支持fat文件系统,幸甚!
RT-Thread本身支持对文件的posix接口,同在linux上一样,open、write等即可完成对文件操作,数据即可以文件形式保存。本文全当文件系统搭建过程的记录,以及对RT-Thread文件系统的浅要分析。

正文

自此切入正题,不去赘述RT-Thread相关的东西,也不去赘述sd卡相关blabla。。。。。。
RT-Thread中使用文件系统大致分为以下步骤:dfs_init()、elm_init()、dfs_mount()。
dfs_init:初始化rtos的系统文件。
elm_init:初始化fat文件系统接口层。
dfs_mount:挂载sd卡到指定文件系统。
好,先跑代码,再理头绪。

dfs_init

/**
 * @addtogroup DFS
 */

/*@{*/

/**
 * this function will initialize device file system.
 */
int dfs_init(void)
{
    /* clear filesystem operations table */
    rt_memset((void *)filesystem_operation_table, 0, sizeof(filesystem_operation_table));
    /* clear filesystem table */
    rt_memset(filesystem_table, 0, sizeof(filesystem_table));
    /* clean fd table */
    rt_memset(fd_table, 0, sizeof(fd_table));

    /* create device filesystem lock */
    rt_mutex_init(&fslock, "fslock", RT_IPC_FLAG_FIFO);

#ifdef DFS_USING_WORKDIR
    /* set current working directory */
    rt_memset(working_directory, 0, sizeof(working_directory));
    working_directory[0] = '/';
#endif
    return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28

一看就是数据初始化的工作嘛,对filesystem_operation_table、filesystem_table、fd_table有个印象,往下看自然就知道都是干嘛用的。

elm_init

int elm_init(void)
{
    /* register fatfs file system */
    dfs_register(&dfs_elm);

    return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

其实,这里是将fat注册进了filesystem_operation_table,而不是filesystem_table。

dfs_mount

int dfs_mount(const char   *device_name,
              const char   *path,
              const char   *filesystemtype,
              unsigned long rwflag,
              const void   *data)

dfs_mount("sd0", "/", "elm", 0, NULL)            
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

此部分作用就是:把一个设备与某个文件系统结合挂载到某个路径下。此处就是:把sd卡0与fat文件系统结合挂载到“/”该路径下。然后就可以用posix读写sd卡了。简单的不要不要的。
巴特,为什么文件系统名称为“elm”,不叫“fat”之类。
dfs_mount看下源码其实就明白了,设备挂载就是根据filesystemtype去filesystem_operation_table表中找匹配的文件系统,匹配之后再将文件系统加入filesystem_table中。

小结

最后以一次open操作理清流程结束本文。
open操作会调用dfs的相关open操作,dfs定义统一的文件系统接口。根据open的path去查找次路径下的文件系统,并调用该文件系统对应的open操作,也就是elm的open操作,elm再调用fat文件系统的open操作。最后涉及到sd卡的读写再回调elm中的设备操作,最后再是调用sd卡的操作接口完成。

结论

1,dfs就是RT-Thread的虚拟文件系统,像linux的vfs一样;
2,dfs以统一操作接口封装不同文件系统的差异;
3,文件系统(如:fat)挂载后,就是rtos知道有这么文件系统,但还无法使用。(没有物理设备,你往哪写数据)
4,设备挂载后与文件系统配对挂载到一个特定路径。(这点和linux好像)
5,文件操作时,根据路径就能找到所属的具体文件系统。
6,elm是啥玩意儿?elm就是fat接入dfs的连接件。由于fat不是针对RT-Thread的,rtos作者本人也没有修改出一稿RT-Thread专用的fat源码,所有就有了elm这一层。其实elm就可以看作是RT-Thread下的fat文件系统–封装fat操作并提供底层硬件操作回调。
7,关于sd卡驱动,RT-Thread有设备驱动接口,本文不涉及了。
8,总的来说dfs这部分不难,同时可能对后续了解linux的vfs时会有些帮助。

题外话

1,我RT-Thread-1.2.2版木有文件的flush接口,也就是只有文件close的时候数据才会被刷到sd卡中,写入的数据size足够大时估计也会自动flush。但是如果希望每次写少量数据也能及时刷到sd卡中,但又不想每次写入都执行一遍open、close。然后么就是修改下dfs的write操作了

int dfs_file_write(struct dfs_fd *fd, const void *buf, rt_size_t len)
{
    struct dfs_filesystem *fs;

    if (fd == RT_NULL)
        return -DFS_STATUS_EINVAL;

    fs = fd->fs;
    if (fs->ops->write == RT_NULL)
        return -DFS_STATUS_ENOSYS;

    //return fs->ops->write(fd, buf, len);
    /*为了flush而添加 by 百里无异 at 2016-3-4*/
    int ret = fs->ops->write(fd, buf, len);
    if (ret > 0) {
        dfs_file_flush(fd);
    }
    return ret;
    /******/
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

正确的做法用该是在posix接口中添加flush操作,这里偷懒了!

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/人工智能uu/article/detail/779850
推荐阅读
相关标签
  

闽ICP备14008679号