@@ -5,7 +5,7 @@ categories:
55 - 内核层
66abbrlink : 4936fe45
77date : 2025-05-19 12:50:00
8- updated : 2025-06-04 12:05 :00
8+ updated : 2025-06-04 17:25 :00
99---
1010
1111<meta name =" referrer " content =" no-referrer " />
@@ -764,7 +764,11 @@ rtems_chain_control *chain = &filesystem_chain;
764764const rtems_filesystem_table_t *table_entry = &rtems_filesystem_table[0 ];
765765```
766766
767- 关于 rtems_filesystem_table,它用于表示挂载的文件系统的信息,并且猜测大概率是预挂载的文件系统的信息。定义如下:
767+ #### variable rtems_filesystem_table
768+
769+ 关于 rtems_filesystem_table,它用于表示挂载的文件系统的信息,并且猜测大概率是预挂载的文件系统的信息。结构体 rtems_filesystem_table_t 前面提到过,两个成员分别代表文件系统的类型名称 type 和文件系统的挂载函数指针 mount_h。
770+
771+ rtems_filesystem_table 的定义如下。其中关于 IMFS 有两个地方提到,一个是文件系统名字叫 "/" 的文件系统,一个是下面的 IMFS 文件系统。他们对应的挂载函数分别叫 IMFS_initialize_support() 和 IMFS_initialize()。
768772
769773``` c
770774const rtems_filesystem_table_t rtems_filesystem_table[] = {
@@ -793,7 +797,216 @@ const rtems_filesystem_table_t rtems_filesystem_table[] = {
793797 {NULL, NULL}};
794798```
795799
796- TODO
800+ ### IMFS_initialize() 和 IMFS_initialize_support()
801+
802+ IMFS_initialize() 的执行流程图如下:
803+
804+ ```mermaid
805+ flowchart TD
806+ A[开始 IMFS_initialize] --> B[调用 calloc 分配并清零 fs_info 内存]
807+ B --> C{fs_info 是否为 NULL}
808+ C -- 是 --> D[设置 errno 为 ENOMEM] --> E[返回 -1, 初始化失败]
809+ C -- 否 --> F[构造 IMFS_mount_data 结构体]
810+ F --> G[填入 fs_info 指针<br>填入文件系统操作集 &IMFS_ops<br>填入默认节点创建控制表 &IMFS_default_mknod_controls]
811+ G --> H[调用 IMFS_initialize_support 进行实际初始化和挂载]
812+ H --> I[返回初始化结果]
813+ ```
814+
815+ 其中填充 IMFS_mount_data 结构体的代码截取如下,可以看出 rtems_filesystem_operations_table 结构体的回调函数是在这里被注册进去的。
816+
817+ ``` c
818+ typedef struct
819+ {
820+ IMFS_fs_info_t *fs_info;
821+ const rtems_filesystem_operations_table *ops;
822+ const IMFS_mknod_controls *mknod_controls;
823+ } IMFS_mount_data;
824+
825+ // 构造挂载所需的初始化数据结构,包括操作集和创建节点控制表。
826+ IMFS_mount_data mount_data = {
827+ .fs_info = fs_info, // 文件系统内部信息。
828+ .ops = &IMFS_ops, // 文件系统操作函数集合。
829+ .mknod_controls = &IMFS_default_mknod_controls // 创建节点控制信息。
830+ };
831+ ```
832+
833+ IMFS_initialize () 最后会调用 IMFS_initialize_support(),IMFS_initialize_support() 的执行流程图如下:
834+
835+ ``` mermaid
836+ flowchart TD
837+ A[开始 IMFS_initialize_support 函数] --> B[将 data 转为 IMFS_mount_data 指针]
838+ B --> C[提取 fs_info 和 mknod_controls]
839+ C --> D[获取 node_control 和 root_node 指针]
840+ D --> E[设置挂载点 mt_entry 的各项字段, 包括 fs_info, ops, pathconf, root 节点信息]
841+ E --> F[调用 IMFS_initialize_node 初始化根目录节点]
842+ F --> G[断言 root_node 不为 NULL]
843+ G --> H[返回 0, 表示初始化成功]
844+ ```
845+
846+ 这其中也做了很多赋值操作,代码片段截取如下。其中 _ rtems_filesystem_file_handlers_r 结构体的回调函数是在这里注册进去的。
847+
848+ ``` c
849+ // 转换传入的 data 参数为具体类型。
850+ mount_data = data;
851+
852+ // 提取文件系统信息和 mknod 控制器。
853+ fs_info = mount_data->fs_info;
854+ fs_info->mknod_controls = mount_data->mknod_controls;
855+
856+ // 获取根目录所用的节点控制器。
857+ node_control = &mount_data->mknod_controls->directory->node_control;
858+
859+ // 获取根节点结构体的地址。
860+ root_node = &fs_info->Root_directory.Node;
861+
862+ // 设置挂载点结构 mt_entry 的基本信息。
863+ mt_entry->fs_info = fs_info; // 文件系统私有数据。
864+ mt_entry->ops = mount_data->ops; // 文件系统操作集。
865+ mt_entry->pathconf_limits_and_options = &IMFS_LIMITS_AND_OPTIONS; // 路径相关限制。
866+
867+ // 设置挂载根目录的节点访问和操作处理函数。
868+ mt_entry->mt_fs_root->location.node_access = root_node;
869+ mt_entry->mt_fs_root->location.handlers = node_control->handlers;
870+ ```
871+
872+ #### IMFS_initialize_node()
873+
874+ IMFS_initialize_support () 最后会调用 IMFS_initialize_node() 函数。该函数用于初始化一个 IMFS 节点(内存文件系统中的目录或文件节点)。根据传入的信息填充节点结构体的基本字段,并调用节点类型控制器提供的初始化回调。成功返回已初始化的节点指针,失败返回 NULL 并设置 errno。
875+
876+ IMFS_initialize_node () 的执行流程图如下:
877+
878+ ``` mermaid
879+ flowchart TD
880+ A[开始 IMFS_initialize_node 函数] --> B{namelen 是否超过 IMFS_NAME_MAX}
881+ B -- 是 --> C[设置 errno 为 ENAMETOOLONG<br>返回 NULL]
882+ B -- 否 --> D[填充节点基本字段 name, namelen, reference_count, st_nlink, control]
883+ D --> E[设置权限和属主信息 mode, uid, gid]
884+ E --> F[获取当前时间 now]
885+ F --> G[设置时间戳 atime, mtime, ctime]
886+ G --> H[调用 node_control 的 node_initialize 回调]
887+ H --> I[返回初始化后的节点指针]
888+ ```
889+
890+ 该函数在设置了节点 node 的信息以后,会调用 node_control 结构体的 node_initialize 回调函数进行 node 初始化。代码片段如下:
891+
892+ ``` c
893+ // 调用节点控制器中定义的初始化函数以执行具体类型的初始化。
894+ return (*node_control->node_initialize)(node, arg);
895+ ```
896+
897+ ### struct IMFS_jnode_tt
898+
899+ IMFS_jnode_tt 是 IMFS 自己设计的 inode 结构,作用和 Linux 中文件系统自己的 inode 结构效果相同,定义如下:
900+
901+ ``` c
902+ // IMFS_jnode_tt 是 IMFS 文件系统中用于表示一个文件或目录的节点结构体。这是内存文件系统(IMFS)中最核心的数据结构之一,包含名称、权限、所有者、时间戳等元数据,以及指向父节点和控制操作的指针。
903+ struct IMFS_jnode_tt
904+ {
905+ // 用于将该节点链接入链表中。
906+ rtems_chain_node Node;
907+
908+ // 指向父节点的指针。
909+ IMFS_jnode_t *Parent;
910+
911+ // 节点名称,不以 \0 结尾(即不是 C 字符串)。
912+ const char *name;
913+
914+ // 节点名称的长度(对应上面的 name)。
915+ uint16_t namelen;
916+
917+ // 文件类型和权限信息(如目录、常规文件、权限位)。
918+ mode_t st_mode;
919+
920+ // 节点的引用计数,用于资源管理。
921+ unsigned short reference_count;
922+
923+ // 硬链接数量(链接计数)。
924+ nlink_t st_nlink;
925+
926+ // 拥有者的用户 ID。
927+ uid_t st_uid;
928+
929+ // 拥有者的组 ID。
930+ gid_t st_gid;
931+
932+ // 最后一次访问时间。
933+ time_t stat_atime;
934+
935+ // 最后一次修改内容的时间。
936+ time_t stat_mtime;
937+
938+ // 最后一次属性更改(如权限、所有者等)的时间。
939+ time_t stat_ctime;
940+
941+ // 节点控制器,定义节点的行为和操作函数。
942+ const IMFS_node_control *control;
943+ };
944+ ```
945+
946+ #### struct IMFS_node_control
947+
948+ struct IMFS_jnode_tt 中除了 inode 的基本信息以外,需要关注的一点就是 struct IMFS_node_control。该结构体定义了 IMFS inode 节点的操作函数,并作统一控制管理。
949+
950+ ``` c
951+ /* *
952+ * @brief IMFS node control.
953+ */
954+ // IMFS_node_control:定义 IMFS 节点类型的操作控制器。
955+ // 每种节点类型(如普通文件、目录、符号链接等)可以拥有自己的 handlers 和初始化、销毁等函数指针。
956+ // 该结构体允许 IMFS 在操作不同类型节点时通过回调机制实现多态行为。
957+ typedef struct
958+ {
959+ // 文件操作处理器集合,包含 open、read、write、ioctl 等函数指针。
960+ // 每种节点类型可以定义不同的 handlers。
961+ const rtems_filesystem_file_handlers_r *handlers;
962+
963+ // 节点初始化函数,在创建该类型节点时调用。
964+ // 通常在 IMFS_initialize_node 中调用,用于执行类型特定的初始化逻辑。
965+ IMFS_node_control_initialize node_initialize;
966+
967+ // 节点删除函数,在执行 unlink/remove 操作时调用。
968+ // 用于处理节点类型特定的清理逻辑,如从父结构中移除等。
969+ IMFS_node_control_remove node_remove;
970+
971+ // 节点销毁函数,在释放节点内存或引用计数归零时调用。
972+ // 通常用于释放节点中私有数据或执行资源回收。
973+ IMFS_node_control_destroy node_destroy;
974+ } IMFS_node_control;
975+ ```
976+
977+ 前面提到,_ rtems_filesystem_file_handlers_r 结构体的回调函数是在 IMFS_initialize_support() 中注册的,最终就来源于 IMFS_node_control 中的 rtems_filesystem_file_handlers_r * handlers。
978+
979+ ``` c
980+ mt_entry->mt_fs_root->location.handlers = node_control->handlers;
981+ ```
982+
983+ 下一步就是找到这些函数最开始是在哪里被注册的。最终在 cpukit/libfs/src/imfs/imfs_linfile.c 中找到了答案:
984+
985+ ``` c
986+ static const rtems_filesystem_file_handlers_r IMFS_linfile_handlers = {
987+ .open_h = IMFS_linfile_open,
988+ .close_h = rtems_filesystem_default_close,
989+ .read_h = IMFS_linfile_read,
990+ .write_h = rtems_filesystem_default_write,
991+ .ioctl_h = rtems_filesystem_default_ioctl,
992+ .lseek_h = rtems_filesystem_default_lseek_file,
993+ .fstat_h = IMFS_stat_file,
994+ .ftruncate_h = rtems_filesystem_default_ftruncate,
995+ .fsync_h = rtems_filesystem_default_fsync_or_fdatasync_success,
996+ .fdatasync_h = rtems_filesystem_default_fsync_or_fdatasync_success,
997+ .fcntl_h = rtems_filesystem_default_fcntl,
998+ .kqfilter_h = rtems_filesystem_default_kqfilter,
999+ .mmap_h = rtems_filesystem_default_mmap,
1000+ .poll_h = rtems_filesystem_default_poll,
1001+ .readv_h = rtems_filesystem_default_readv,
1002+ .writev_h = rtems_filesystem_default_writev};
1003+
1004+ const IMFS_node_control IMFS_node_control_linfile = {
1005+ .handlers = &IMFS_linfile_handlers,
1006+ .node_initialize = IMFS_node_initialize_linfile,
1007+ .node_remove = IMFS_node_remove_default,
1008+ .node_destroy = IMFS_node_destroy_default};
1009+ ```
7971010
7981011# 参考文档
7991012
0 commit comments