@@ -5,7 +5,7 @@ categories:
55 - 内核层
66abbrlink : 4936fe45
77date : 2025-05-19 12:50:00
8- updated : 2025-05-22 16:30 :00
8+ updated : 2025-05-25 15:50 :00
99---
1010
1111<meta name =" referrer " content =" no-referrer " />
@@ -138,7 +138,7 @@ struct _rtems_filesystem_file_handlers_r
138138};
139139```
140140
141- 另一个成员是 struct rtems_filesystem_mount_table_entry_tt。这个结构体代表一个完整的挂载项(mount entry), Rtems 会为每个挂载的文件系统维护一份这样的结构体实例,挂载后保存在全局挂载表中。它贯穿于路径解析、节点定位、读写操作、卸载管理等核心逻辑中。简而言之,它是挂载文件系统的核心描述对象 。
141+ 另一个成员是 struct rtems_filesystem_mount_table_entry_tt。这个结构体的作用是为每一个已挂载的文件系统提供一个集中式的描述,包含了文件系统的根节点信息、挂载点、类型、设备、访问控制状态等关键信息。 Rtems 会维护一个这样的挂载表链表,每个表项都是这个结构体的一个实例。在挂载和卸载文件系统时,Rtems 会对这个结构体进行相应的初始化、操作或释放。文件系统的挂载、查找路径、访问权限、卸载等都依赖于这个结构体中记录的信息 。
142142
143143``` c
144144// 表示一个挂载的文件系统实例,是 Rtems 文件系统挂载表中的一项。
@@ -191,6 +191,70 @@ struct rtems_filesystem_mount_table_entry_tt
191191};
192192```
193193
194+ 在 RTEMS 中,文件系统的操作由 rtems_filesystem_operations_table 结构体统一管理,它定义了路径解析、节点创建、删除、克隆等核心操作函数,作用上相当于 Linux 中的 inode_operations。每个挂载的文件系统通过 rtems_filesystem_mount_table_entry_t 表示,类似于 Linux 的 super_block,其中包含了指向操作表 ops 的指针。当用户发起如 open、read、write 等文件访问请求时,系统首先通过 eval_path_h 函数解析路径并定位到目标节点,然后使用该节点中挂载的 rtems_filesystem_file_handlers_r(类似 Linux 的 file_operations)来完成具体操作。整个设计将挂载管理、路径解析和文件操作职责分离,形成清晰的模块边界,同时借鉴了 Linux 文件系统架构的思想。
195+
196+ ``` c
197+ struct _rtems_filesystem_operations_table
198+ {
199+ // 挂载点加锁函数,防止并发访问挂载点结构。
200+ rtems_filesystem_mt_entry_lock_t lock_h;
201+
202+ // 挂载点解锁函数,与 lock_h 成对使用。
203+ rtems_filesystem_mt_entry_unlock_t unlock_h;
204+
205+ // 路径解析函数,将路径转换为文件系统节点。
206+ rtems_filesystem_eval_path_t eval_path_h;
207+
208+ // 创建硬链接的函数。
209+ rtems_filesystem_link_t link_h;
210+
211+ // 判断两个节点是否表示同一对象的函数。
212+ rtems_filesystem_are_nodes_equal_t are_nodes_equal_h;
213+
214+ // 创建文件系统节点(如文件、目录、设备节点)的函数。
215+ rtems_filesystem_mknod_t mknod_h;
216+
217+ // 删除文件系统节点的函数。
218+ rtems_filesystem_rmnod_t rmnod_h;
219+
220+ // 更改节点权限的函数,相当于 chmod。
221+ rtems_filesystem_fchmod_t fchmod_h;
222+
223+ // 更改节点所有者信息的函数,相当于 chown。
224+ rtems_filesystem_chown_t chown_h;
225+
226+ // 克隆节点的函数,通常用于目录项引用增加时复制节点。
227+ rtems_filesystem_clonenode_t clonenod_h;
228+
229+ // 释放节点资源的函数,通常在节点引用减少到 0 时调用。
230+ rtems_filesystem_freenode_t freenod_h;
231+
232+ // 文件系统挂载处理函数,处理实际挂载逻辑。
233+ rtems_filesystem_mount_t mount_h;
234+
235+ // 文件系统卸载处理函数,释放挂载相关资源。
236+ rtems_filesystem_unmount_t unmount_h;
237+
238+ // 文件系统自定义卸载钩子,用于挂载入口被清理时的回调。
239+ rtems_filesystem_fsunmount_me_t fsunmount_me_h;
240+
241+ // 修改节点时间戳信息的函数,相当于 utimensat。
242+ rtems_filesystem_utimens_t utimens_h;
243+
244+ // 创建符号链接的函数。
245+ rtems_filesystem_symlink_t symlink_h;
246+
247+ // 读取符号链接目标路径的函数。
248+ rtems_filesystem_readlink_t readlink_h;
249+
250+ // 重命名文件或目录的函数。
251+ rtems_filesystem_rename_t rename_h;
252+
253+ // 获取文件系统统计信息的函数,如空间大小、inode 数等。
254+ rtems_filesystem_statvfs_t statvfs_h;
255+ };
256+ ```
257+
194258#### rtems_libio_allocate()
195259
196260open 函数中分配文件描述符结构使用的函数是 rtems_libio_allocate(),定义如下:
@@ -868,6 +932,143 @@ int rtems_filesystem_register(
868932}
869933```
870934
935+ #### rtems_filesystem_fsmount_me_t
936+
937+ rtems_filesystem_fsmount_me_t 是一个函数指针,定义如下:
938+
939+ ```c
940+ /**
941+ * @brief Initializes a file system instance.
942+ *
943+ * This function must initialize the file system root node in the mount table
944+ * entry.
945+ *
946+ * @param[in] mt_entry The mount table entry.
947+ * @param[in] data The data provided by the user.
948+ *
949+ * @retval 0 Successful operation.
950+ * @retval -1 An error occurred. The errno is set to indicate the error.
951+ */
952+
953+ // 定义一个函数指针类型 rtems_filesystem_fsmount_me_t,返回值为 int。
954+ // 返回值为 0 表示挂载成功,-1 表示失败并设置 errno。
955+ typedef int (*rtems_filesystem_fsmount_me_t)(
956+ // 第一个参数是挂载表项指针,表示要挂载的文件系统实例。
957+ rtems_filesystem_mount_table_entry_t *mt_entry,
958+ // 第二个参数是用户提供的初始化数据(例如设备路径或选项)。
959+ const void *data);
960+ ```
961+
962+ struct rtems_filesystem_mount_table_entry_t 结构体的作用是为每一个已挂载的文件系统提供一个集中式的描述,包含了文件系统的根节点信息、挂载点、类型、设备、访问控制状态等关键信息。Rtems 会维护一个这样的挂载表链表,每个表项都是这个结构体的一个实例。在挂载和卸载文件系统时,Rtems 会对这个结构体进行相应的初始化、操作或释放。文件系统的挂载、查找路径、访问权限、卸载等都依赖于这个结构体中记录的信息。
963+
964+ 关于 struct rtems_filesystem_mount_table_entry_tt 和 struct _ rtems_filesystem_operations_table,前面在 struct rtems_libio_t 的时候提到过,不再赘述。
965+
966+ ### rtems_fsmount
967+
968+ ``` c
969+ // 批量挂载文件系统的函数。
970+ // 根据传入的 fstab 表顺序创建挂载点并执行 mount 操作。
971+ // 挂载成功或失败根据用户提供的 report/abort 标志控制终止行为。
972+ // 返回 0 表示全部挂载成功,返回 -1 表示失败并设置 errno。
973+ int rtems_fsmount (
974+ const rtems_fstab_entry *fstab_ptr, // 指向文件系统挂载表的首项。
975+ size_t fstab_count, // 表项数量。
976+ size_t *fail_idx // 如果挂载失败,记录失败的索引。
977+ )
978+ {
979+ int rc = 0; // 函数最终返回值,0 表示成功。
980+ int tmp_rc; // 临时返回值,用于每一项操作的状态。
981+ size_t fstab_idx = 0; // 当前处理的表项索引。
982+ bool terminate = false; // 是否中止挂载过程。
983+
984+ // 遍历挂载表中的所有条目,逐项处理。
985+ while (!terminate && (fstab_idx < fstab_count))
986+ {
987+ tmp_rc = 0;
988+
989+ // 步骤 1:尝试创建挂载点路径(如 /mnt/sdcard)。
990+ if (tmp_rc == 0)
991+ {
992+ tmp_rc = rtems_mkdir(fstab_ptr->target, S_IRWXU | S_IRWXG | S_IRWXO);
993+ if (tmp_rc != 0)
994+ {
995+ // 若启用错误报告标志,打印错误信息。
996+ if (0 != (fstab_ptr->report_reasons & FSMOUNT_MNTPNT_CRTERR))
997+ {
998+ fprintf (stdout, "fsmount: creation of mount point \" %s\" failed: %s\n",
999+ fstab_ptr->target,
1000+ strerror(errno));
1001+ }
1002+ // 若启用失败终止标志,设置中止挂载流程。
1003+ if (0 != (fstab_ptr->abort_reasons & FSMOUNT_MNTPNT_CRTERR))
1004+ {
1005+ terminate = true;
1006+ rc = tmp_rc;
1007+ }
1008+ }
1009+ }
1010+
1011+ // 步骤 2:尝试执行挂载操作。
1012+ if (tmp_rc == 0)
1013+ {
1014+ tmp_rc = mount(fstab_ptr->source,
1015+ fstab_ptr->target,
1016+ fstab_ptr->type,
1017+ fstab_ptr->options,
1018+ NULL);
1019+ if (tmp_rc != 0)
1020+ {
1021+ // 挂载失败,打印错误信息(若配置了报告标志)。
1022+ if (0 != (fstab_ptr->report_reasons & FSMOUNT_MNT_FAILED))
1023+ {
1024+ fprintf (stdout, "fsmount: mounting of \" %s\" to \" %s\" failed: %s\n",
1025+ fstab_ptr->source,
1026+ fstab_ptr->target,
1027+ strerror(errno));
1028+ }
1029+ // 挂载失败,根据配置判断是否终止流程。
1030+ if (0 != (fstab_ptr->abort_reasons & FSMOUNT_MNT_FAILED))
1031+ {
1032+ terminate = true;
1033+ rc = tmp_rc;
1034+ }
1035+ }
1036+ else
1037+ {
1038+ // 挂载成功,根据配置打印信息。
1039+ if (0 != (fstab_ptr->report_reasons & FSMOUNT_MNT_OK))
1040+ {
1041+ fprintf(stdout, "fsmount: mounting of \" %s\" to \" %s\" succeeded\n",
1042+ fstab_ptr->source,
1043+ fstab_ptr->target);
1044+ }
1045+ // 挂载成功,根据配置判断是否终止流程。
1046+ if (0 != (fstab_ptr->abort_reasons & FSMOUNT_MNT_OK))
1047+ {
1048+ terminate = true;
1049+ }
1050+ }
1051+ }
1052+
1053+ // 步骤 3:准备处理下一条挂载表项。
1054+ if (!terminate)
1055+ {
1056+ fstab_ptr++;
1057+ fstab_idx++;
1058+ }
1059+ }
1060+
1061+ // 如果用户提供了失败索引记录指针,则写入最后处理的索引。
1062+ if (fail_idx != NULL)
1063+ {
1064+ *fail_idx = fstab_idx;
1065+ }
1066+
1067+ // 返回整体挂载操作的状态。
1068+ return rc;
1069+ }
1070+ ```
1071+
8711072# 参考文档
8721073
87310741 . [ RTEMS Filesystem Design Guide (6.1). — RTEMS Filesystem Design Guide 6.1 (22nd January 2025) documentation] ( https://docs.rtems.org/docs/6.1/filesystem/index.html )
0 commit comments