1. 介绍

文件系统,是对一个存储设备上的数据和元数据进行组织的机制,它是操作系统管理持久性数据的子系统,提供数据存储和访问功能。

将一个文件系统与一个存储设备关联起来的过程叫做挂载(mount),挂载时会将一个文件系统附着到当前文件系统层次结构中(根),在执行挂载时,需要提供文件系统类型、文件系统和一个挂载点。1.1 Nuttx文件系统介绍

Nuttx包含了一个可选的、可扩展的文件系统,这个文件系统可以完全省略掉,Nuttx不依赖于任何文件系统的存在。伪根文件系统

可以通过将CONFIG_NFILE_DESCRIPTOS设置成非零值,来使能这个内存中的伪文件系统。它是一个内存文件系统,因为它不需要任何存储介质或块驱动程序的支持。文件系统内容是通过标准文件系统操作(open, close, read, write, etc.)实时生成的。在这个意义上,它是一个伪文件系统(Linux的/proc也称为伪文件系统)。

可以通过伪文件系统访问用户提供的任何数据或逻辑。支持对字符设备驱动及块设备驱动节点在伪文件系统任何目录中的内建,不过按照惯例,都习惯放在/dev伪文件系统目录中。

文件系统挂载

简单的内存文件系统,可通过挂载块设备来扩展,这些块设备提供大容量存储设备支持以实现真正的文件系统访问。Nuttx支持标准的mount()命令,该命令允许块驱动程序将文件系统绑定到伪文件系统中的挂载点上。目前,Nuttx支持VFAT文件系统。

与Linux比较

从编程的角度来看,Nuttx文件系统看起来与Linux文件系统非常类似,但是,有一个根本的区别:Nuttx根文件系统是一个伪文件系统,而真正的文件系统可以挂载在伪文件系统中;相比之下,在典型的Linux安装中,Linux根文件系统是一个真正的文件系统,伪文件系统挂载在真正的根文件系统中。Nuttx选择的方法,旨在提供从非常小的平台到中等平台等的支持,以便具备更好的可扩展性。

2. 数据结构2.1 struct inode

inode是文件系统中最重要的结构,存放基本的数据:struct inode{

FAR struct inode *i_peer;     /* Link to same level inode */

FAR struct inode *i_child;    /* Link to lower level inode */

int16_t           i_crefs;    /* References to inode */

uint16_t          i_flags;    /* Flags for inode */

union inode_ops_u u;          /* Inode operations */#ifdef CONFIG_FILE_MODE

mode_t            i_mode;     /* Access mode flags */#endif

FAR void         *i_private;  /* Per inode driver private data */

char              i_name[1];  /* Name of inode (variable) */};i_peer和i_child会将inode组织成树状结构;

i_flags用于表明文件类型,比如Character driver/Block driver/Mount point/Special OS type/Named semaphore/Message Queue/Shared memory region/Soft link等

i_private在驱动中,通常用于存放私有数据;

union inode_ops_u u,存放对inode的操作函数集,而针对不同的inode类型,对应不同的操作函数;2.2 union inode_ops_uunion inode_ops_u

{

FAR const struct file_operations     *i_ops;    /* Driver operations for inode */#ifndef CONFIG_DISABLE_MOUNTPOINT

FAR const struct block_operations    *i_bops;   /* Block driver operations */

FAR const struct mountpt_operations  *i_mops;   /* Operations on a mountpoint */#endif#ifdef CONFIG_FS_NAMED_SEMAPHORES

FAR struct nsem_inode_s              *i_nsem;   /* Named semaphore */#endif#ifndef CONFIG_DISABLE_MQUEUE

FAR struct mqueue_inode_s            *i_mqueue; /* POSIX message queue */#endif#ifdef CONFIG_PSEUDOFS_SOFTLINKS

FAR char                             *i_link;   /* Full path to link target */#endif};

主要有三个操作函数集,此外由于VFS也维护了像Named semaphores/Message Queues/Shared memory等资源,但是这些资源又不像其他类型的文件有函数操作集,算是special case,也放在这个结构中。struct file_operations,存放对驱动的操作,一般在实现驱动程序中,都会去实现对应的函数操作;struct file_operations{

/* The device driver open method differs from the mountpoint open method */

int     (*open)(FAR struct file *filep);  /* The following methods must be identical in signature and position because

* the struct file_operations and struct mountp_operations are treated like

* unions.

*/

int     (*close)(FAR struct file *filep);  ssize_t (*read)(FAR struct file *filep, FAR char *buffer, size_t buflen);  ssize_t (*write)(FAR struct file *filep, FAR const char *buffer, size_t buflen);  off_t   (*seek)(FAR struct file *filep, off_t offset, int whence);  int     (*ioctl)(FAR struct file *filep, int cmd, unsigned long arg);  /* The two structures need not be common after this point */#ifndef CONFIG_DISABLE_POLL

int     (*poll)(FAR struct file *filep, struct pollfd *fds, bool setup);#endif#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS

int     (*unlink)(FAR struct inode *inode);#endif};struct block_operations,存放块设备的操作函数集,用于文件系统转换;struct block_operations

{  int     (*open)(FAR struct inode *inode);  int     (*close)(FAR struct inode *inode);

ssize_t (*read)(FAR struct inode *inode, FAR unsigned char *buffer,

size_t start_sector, unsigned int nsectors);

ssize_t (*write)(FAR struct inode *inode, FAR const unsigned char *buffer,

size_t start_sector, unsigned int nsectors);  int     (*geometry)(FAR struct inode *inode, FAR struct geometry *geometry);  int     (*ioctl)(FAR struct inode *inode, int cmd, unsigned long arg);#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS

int     (*unlink)(FAR struct inode *inode);#endif};struct mountpt_operations,由一个文件系统提供,用于描述挂载点;struct inode;struct fs_dirent_s;struct stat;struct statfs;struct mountpt_operations

{  /* The mountpoint open method differs from the driver open method

* because it receives (1) the inode that contains the mountpoint

* private data, (2) the relative path into the mountpoint, and (3)

* information to manage privileges.

*/

int     (*open)(FAR struct file *filep, FAR const char *relpath,            int oflags, mode_t mode);  /* The following methods must be identical in signature and position

* because the struct file_operations and struct mountp_operations are

* treated like unions.

*/

int     (*close)(FAR struct file *filep);

ssize_t (*read)(FAR struct file *filep, FAR char *buffer, size_t buflen);

ssize_t (*write)(FAR struct file *filep, FAR const char *buffer,

size_t buflen);

off_t   (*seek)(FAR struct file *filep, off_t offset, int whence);  int     (*ioctl)(FAR struct file *filep, int cmd, unsigned long arg);  /* The two structures need not be common after this point. The following

* are extended methods needed to deal with the unique needs of mounted

* file systems.

*

* Additional open-file-specific mountpoint operations:

*/

int     (*sync)(FAR struct file *filep);  int     (*dup)(FAR const struct file *oldp, FAR struct file *newp);  int     (*fstat)(FAR const struct file *filep, FAR struct stat *buf);  /* Directory operations */

int     (*opendir)(FAR struct inode *mountpt, FAR const char *relpath,

FAR struct fs_dirent_s *dir);  int     (*closedir)(FAR struct inode *mountpt,

FAR struct fs_dirent_s *dir);  int     (*readdir)(FAR struct inode *mountpt,

FAR struct fs_dirent_s *dir);  int     (*rewinddir)(FAR struct inode *mountpt,

FAR struct fs_dirent_s *dir);  /* General volume-related mountpoint operations: */

int     (*bind)(FAR struct inode *blkdriver, FAR const void *data,

FAR void **handle);  int     (*unbind)(FAR void *handle, FAR struct inode **blkdriver,            unsigned int flags);  int     (*statfs)(FAR struct inode *mountpt, FAR struct statfs *buf);  /* Operations on paths */

int     (*unlink)(FAR struct inode *mountpt, FAR const char *relpath);  int     (*mkdir)(FAR struct inode *mountpt, FAR const char *relpath,

mode_t mode);  int     (*rmdir)(FAR struct inode *mountpt, FAR const char *relpath);  int     (*rename)(FAR struct inode *mountpt, FAR const char *oldrelpath,

FAR const char *newrelpath);  int     (*stat)(FAR struct inode *mountpt, FAR const char *relpath,

FAR struct stat *buf);  /* NOTE:  More operations will be needed here to support:  disk usage

* stats file stat(), file attributes, file truncation, etc.

*/};2.3 struct file一个打开的文件对应一个struct file结构,在该结构中包含了inode,用于描述文件的类型以及对应的函数操作集。struct file{

int               f_oflags;   /* Open mode flags */

off_t             f_pos;      /* File position */

FAR struct inode *f_inode;    /* Driver or file system interface */

void             *f_priv;     /* Per file driver private data */};在每个进程中,struct tcb_s结构中都有一个struct filelist结构,用于维护打开的文件,当一个进程调用POSIX接口open来打开时,会得到文件描述符,文件描述符对应的就是这个文件数组的索引值。struct filelist{

sem_t   fl_sem;               /* Manage access to the file list */

struct file fl_files[CONFIG_NFILE_DESCRIPTORS];}

3. 原理分析3.1 框架分析

架构框图如下所示:

文件系统框图用户层,通过系统调用调到VFS层的通用接口;

VFS层,相当于一个适配层,用于对接不同的实际文件系统;

实际文件系统层,典型的情况下一个文件系统都需要绑定到块设备驱动程序上,而一些不太典型的情况是不需要块设备驱动,比如伪文件系统(BINFS、PROCFS)和MTD文件系统(NXFFS)。在Nuttx中,需要块设备驱动的文件系统为:FAT、ROMFS、SMARTFS;而不需要块设备驱动的文件系统为:NXFFS、BINFS、PROCFS、NFS、TMPFS等;

MTD,Memory Technology Devices,向上提供MTD接口,向下对接不同的硬件设备;3.2 mount流程

mount()函数用于将source块设备指定的文件系统与根文件系统中target指定的路径名关联在一起。

在讲mount()之前,需要先了解一下数据结构:struct fsmap_tstruct fsmap_t{

FAR const char                      *fs_filesystemtype;

FAR const struct mountpt_operations *fs_mops;};

这个结构完成的就是文件系统名字和对应的操作函数集的映射,在mount()函数中会根据对应的文件系统名字去查找struct mountpt_operations。struct mountpt_operations

这个数据结构在上文中介绍过了,有一个函数需要特别注意一下:int     (*bind)(FAR struct inode *blkdriver, FAR const void *data, FAR void **handle);

该函数用于将文件系统与某个块设备驱动进行绑定。

mount()关键代码如下:int mount(FAR const char *source, FAR const char *target,

FAR const char *filesystemtype, unsigned long mountflags,

FAR const void *data){#if defined(BDFS_SUPPORT) || defined(NONBDFS_SUPPORT)#ifdef BDFS_SUPPORT

FAR struct inode *blkdrvr_inode = NULL;#endif

FAR struct inode *mountpt_inode;

FAR const struct mountpt_operations *mops;#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS

struct inode_search_s desc;#endif

void *fshandle;  int errcode;  int ret;  /* Verify required pointer arguments */

DEBUGASSERT(target && filesystemtype);  /* Find the specified filesystem.  Try the block driver file systems first */#ifdef BDFS_SUPPORT

if (source && (mops = mount_findfs(g_bdfsmap, filesystemtype)) != NULL)

{      /* Make sure that a block driver argument was provided */

DEBUGASSERT(source);      /* Find the block driver */

ret = find_blockdriver(source, mountflags, &blkdrvr_inode);      if (ret

{

ferr("ERROR: Failed to find block driver %s\n", source);

errcode = -ret;          goto errout;

}

}  else#endif /* BDFS_SUPPORT */#ifdef NONBDFS_SUPPORT  if ((mops = mount_findfs(g_nonbdfsmap, filesystemtype)) != NULL)

{

}  else#endif /* NONBDFS_SUPPORT */

{

ferr("ERROR: Failed to find file system %s\n", filesystemtype);

errcode = ENODEV;      goto errout;

}

inode_semtake();#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS

/* Check if the inode already exists */

SETUP_SEARCH(&desc, target, false);

ret = inode_find(&desc);  if (ret >= 0)

{      /* Successfully found.  The reference count on the inode has been

* incremented.

*/

mountpt_inode = desc.node;

DEBUGASSERT(mountpt_inode != NULL);      /* But is it a directory node (i.e., not a driver or other special

* node)?

*/

if (INODE_IS_SPECIAL(mountpt_inode))

{

ferr("ERROR: target %s exists and is a special node\n", target);

errcode = -ENOTDIR;

inode_release(mountpt_inode);          goto errout_with_semaphore;

}

}  else#endif  /* Insert a dummy node -- we need to hold the inode semaphore

* to do this because we will have a momentarily bad structure.

* NOTE that the new inode will be created with an initial reference

* count of zero.

*/

{

ret = inode_reserve(target, &mountpt_inode);      if (ret

{          /* inode_reserve can fail for a couple of reasons, but the most likely

* one is that the inode already exists. inode_reserve may return:

*

*  -EINVAL - 'path' is invalid for this operation

*  -EEXIST - An inode already exists at 'path'

*  -ENOMEM - Failed to allocate in-memory resources for the operation

*/

ferr("ERROR: Failed to reserve inode for target %s\n", target);

errcode = -ret;          goto errout_with_semaphore;

}

}  /* Bind the block driver to an instance of the file system.  The file

* system returns a reference to some opaque, fs-dependent structure

* that encapsulates this binding.

*/

if (!mops->bind)

{      /* The filesystem does not support the bind operation ??? */

ferr("ERROR: Filesystem does not support bind\n");

errcode = EINVAL;      goto errout_with_mountpt;

}  /* Increment reference count for the reference we pass to the file system */#ifdef BDFS_SUPPORT#ifdef NONBDFS_SUPPORT

if (blkdrvr_inode)#endif

{

blkdrvr_inode->i_crefs++;

}#endif

/* On failure, the bind method returns -errorcode */#ifdef BDFS_SUPPORT

ret = mops->bind(blkdrvr_inode, data, &fshandle);#else

ret = mops->bind(NULL, data, &fshandle);#endif

if (ret != 0)

{      /* The inode is unhappy with the blkdrvr for some reason.  Back out

* the count for the reference we failed to pass and exit with an

* error.

*/

ferr("ERROR: Bind method failed: %d\n", ret);#ifdef BDFS_SUPPORT#ifdef NONBDFS_SUPPORT

if (blkdrvr_inode)#endif

{

blkdrvr_inode->i_crefs--;

}#endif

errcode = -ret;      goto errout_with_mountpt;

}  /* We have it, now populate it with driver specific information. */

INODE_SET_MOUNTPT(mountpt_inode);

mountpt_inode->u.i_mops  = mops;#ifdef CONFIG_FILE_MODE

mountpt_inode->i_mode    = mode;#endif

mountpt_inode->i_private = fshandle;

inode_semgive();  /* We can release our reference to the blkdrver_inode, if the filesystem

* wants to retain the blockdriver inode (which it should), then it must

* have called inode_addref().  There is one reference on mountpt_inode

* that will persist until umount2() is called.

*/...

}

完成的工作主要有:调用mount_findfs()函数,根据传入的参数filesystemtype来找到对应的文件系统操作函数集mops,如果是需要块设备支持的文件系统,则需要调用find_blockdriver()来查找传入参数source对应的块设备驱动;

根据传入参数target,来查找需要mount的路径对应的inode节点,如果没有的话需要调用inode_reserve()创建一个mountpt_inode;

调用mops->bind()函数将文件系统与块设备驱动进行绑定,如果不需要块设备支持的文件系统,bind()函数可能不需要做特殊处理, 而在需要块设备支持的文件系统中,bind()函数最终会将该文件系统的整体状态都传出来,保存在fshandle中;

更新挂载点mountpt_inode的内容,包括操作函数集mops,以及将fshandle保存的文件系统的整体状态放置到mountpt_inode结构中的i_private字段中。当打开这个挂载点mountpt_inode时,便可以根据这个字段来取出对应的信息。

作者:Loyen

链接:https://www.jianshu.com/p/887cffbc3e7d

nuttx和linux区别,Nuttx文件系统相关推荐

  1. Linux 操作系统原理 — 文件系统 — 存储布局

    目录 文章目录 目录 磁盘分区 MBR 与分区表 创建 MBR 分区 创建 GPT 分区 分区的格式化 分区的特性 引导块 空闲空间块 inode 区块.data block 区块与超级块 LVM 与 ...

  2. Linux系统篇-文件系统虚拟文件系统

    看了之前的关于Linux内存管理和进程调度的文章,相比读者们应该对Linux有了大致的了解,本文的主题是Linux虚拟文件系统.闲话少说,开始! 1.软链接和硬链接的区别 我们知道文件都有文件名与数据 ...

  3. Linux的ext4文件系统学习笔记

    补充:设备独立性 Linux中,设备驱动以文件形式表示,用户操作逻辑设备就是操作文件,而不是具体的物理设备,也就是说,用户操作的是功能,是黑箱,而不是真正的实体. APP操作的都是逻辑设备,而逻辑设备 ...

  4. Linux下的文件系统与目录系统简介

    Linux下的文件系统与目录系统简介 一. 文件系统 LINUX有四种基本文件系统类型:普通文件.目录文件.连接文件和特殊文件,可用file命令来识别. 普通文件:如文本文件.C语言元代码.SHELL ...

  5. grub linux rootfs,rootfs文件系统(笔记)(草稿)

    文件系统简介 文件系统就是个软件,帮用户来管理一些二进制的信息,管理外存上存储的这些二进制 各种文件在内存中都是以二进制的形式来存在的,如果没有文件系统,用户就需要自己去决定这些二进制的东西是什么,需 ...

  6. linux 删除分区_详解linux系统架构--文件系统体系

    概述 之前已经对Linux系统架构的内核部分单独做了深入介绍,今天就拿Linux系统架构中的文件系统做一下介绍吧~先介绍下概念: 文件系统是文件存放在磁盘等存储设备上的组织方法.Linux系统能支持多 ...

  7. 马哥学习周总结第一周→linux简介、’文件系统及基础命令------李洋个人笔记。...

    linux计算机的设备有两种 1 字符设备(顺序数据) 键盘,显示器 共同点是数据交换时是一个一个字符来进行的. 2 块设备(随机数据) 硬盘 交换数据按包为单位进行. Linux的文件:在存储空间存 ...

  8. 在Linux中查找文件系统类型的7种方法(ext2,ext3或ext4)

    文件系统是在存储磁盘或分区上命名,存储,检索和更新文件的方式.文件在磁盘上的组织方式. 文件系统分为两个部分:用户数据和元数据(文件名,创建时间,修改时间,大小和在目录层次结构中的位置等). 在本指南 ...

  9. Linux操作系统之文件系统详解

    目录 Linux内核中的五大子系统 1.文件系统的基本组成 2.常见文件系统的类型 1.硬盘的文件系统:file system 2.网络文件系统 3.交换分区的文件系统:swap Linux文件系统经 ...

最新文章

  1. 启动服务 stisvc 以运行服务器,系统日志:事件类型: 警告 事件来源: b57w2k 怎么回事?...
  2. 计算机设备维修税率是多少,设备维修税率是多少
  3. proteus跑马灯仿真_不花费一分钱,实现跑马灯编程实验
  4. docker版本包 乌班图_Ubuntu安装Docker方式一:软件包安装
  5. java 强制类型转换告警_java-对未声明的强制转换返回警告
  6. 公有云私有云的区别_私有云 vs. 公有云:谁更安全?
  7. 网页加载出现没有合适的负载均衡器_一篇文章彻底了解清楚什么是负载均衡
  8. 如何在教学中利用计算机网络,教师论苑(二十二)| 利用XMind思维导图优化计算机网络基础课堂教学...
  9. 权限系统设计学习总结(1)——多租户的RBAC权限管理
  10. RK3399外设驱动之I2C驱动
  11. 网狐6603 创建游戏流程
  12. ipad云计算机,过气iPad2还能这么玩!用云电脑玩PC云游戏
  13. word一键生成ppt 分页_PPT插入word自动分页
  14. 如何安装虚拟机———一台电脑,多个系统体验
  15. HTTP请求状态码集合
  16. 实施微前端的六种方式
  17. R沟通|Typora字体颜色设置
  18. 网站建设 之 用js写wasm
  19. 《安富莱嵌入式周报》第261期:2022.04.11--2022.04.17
  20. 22岁失去 “万亿美金机会”,28岁被硅谷最牛孵化器录取,30岁他的经历被拍成电视剧...

热门文章

  1. 如何简单地通过网页下载付费音乐?
  2. 网络安全专业就业怎么样呢?
  3. 推荐一个在线编程的网站
  4. JSP旅游网站设计与实现
  5. 前端学习必须掌握知识点
  6. Java实现BST:搜索二叉树
  7. 计算机考研复试【C++重点知识笔记面试题】
  8. mysql 审计日志_MYSQL_审计日志查看
  9. 注册kaggle不显示验证码(Captcha must be filled out)如何解决?
  10. ARCGIS之土地报备坐标(报盘数据)txt批量导出工具