@@ -5,7 +5,7 @@ categories:
55 - 内核层
66abbrlink : 4936fe45
77date : 2025-05-19 12:50:00
8- updated : 2025-05-26 11:05 :00
8+ updated : 2025-06-02 17:15 :00
99---
1010
1111<meta name =" referrer " content =" no-referrer " />
@@ -16,6 +16,8 @@ RTEMS(Real‑Time Executive for Multiprocessor Systems)是一款始于 1988
1616
1717本文章用于记录阅读 Rtems 内核源码的笔记,尝试理解其中的逻辑。Rtems 内核的版本是 6.1,在线代码网站见 [ https://rtems.davidingplus.cn/lxr/source/ ] ( https://rtems.davidingplus.cn/lxr/source/ ) 。
1818
19+ 本文章中涉及到的源码摘抄见项目 [ DavidingPlus/rtems-source-code: Rtems 源码阅读。] ( https://github.com/DavidingPlus/rtems-source-code ) 。
20+
1921<!-- more -->
2022
2123# 文件系统
@@ -343,7 +345,10 @@ rtems_libio_iops 是 Rtems 预先分配的 I/O 控制块数组,配置了 CONFI
343345
344346``` c
345347#if CONFIGURE_MAXIMUM_FILE_DESCRIPTORS > 0
346- rtems_libio_t rtems_libio_iops[ CONFIGURE_MAXIMUM_FILE_DESCRIPTORS ];
348+ rtems_libio_t rtems_libio_iops[ CONFIGURE_MAXIMUM_FILE_DESCRIPTORS] ;
349+
350+ const uint32_t rtems_libio_number_iops = RTEMS_ARRAY_SIZE(rtems_libio_iops);
351+ #endif
347352```
348353
349354#### do_open()
@@ -634,19 +639,25 @@ close() 函数的源码如下。在前面更改完状态标志位后,还是会
634639``` c
635640int close (int fd)
636641{
637- rtems_libio_t * iop; // 指向文件描述符对应的 I/O 对象。
638- unsigned int flags; // 当前 I/O 对象的状态标志位。
639- int rc; // 用于保存最终返回值。
642+ // 指向文件描述符对应的 I/O 对象。
643+ rtems_libio_t * iop;
644+
645+ // 当前 I/O 对象的状态标志位。
646+ unsigned int flags;
647+
648+ // 用于保存最终返回值。
649+ int rc;
640650
641651 // 检查文件描述符是否越界。
642652 if ((uint32_t)fd >= rtems_libio_number_iops)
643653 {
644- rtems_set_errno_and_return_minus_one(EBADF); // 错误:Bad file descriptor。
654+ // 错误:Bad file descriptor。
655+ rtems_set_errno_and_return_minus_one(EBADF);
645656 }
646657
647- // 根据 fd 获取对应的 I/O 对象。
648- /**
649- * 这个实现如我所料。
658+ /*
659+ * 根据 fd 获取对应的 I/O 对象。
660+ * 实现类似于:
650661 * static inline rtems_libio_t *rtems_libio_iop(int fd)
651662 * {
652663 * return &rtems_libio_iops[fd];
@@ -657,11 +668,18 @@ int close(int fd)
657668 // 读取该对象当前的标志。
658669 flags = rtems_libio_iop_flags(iop);
659670
660- // 这段循环代码的作用是:在线程安全的前提下,把 I/O 对象的 “打开” 标志(LIBIO_FLAGS_OPEN)给清除掉,并且检测有没有正在并发操作导致的冲突。
671+ /*
672+ * 这段循环代码的作用是:在线程安全的前提下,
673+ * 把 I/O 对象的 “打开” 标志(LIBIO_FLAGS_OPEN)清除掉,
674+ * 并且检测有没有正在并发操作导致的冲突。
675+ */
661676 while (true)
662677 {
663- unsigned int desired; // 期望写入的新标志。
664- bool success; // CAS 成功与否。
678+ // 期望写入的新标志。
679+ unsigned int desired;
680+
681+ // CAS 成功与否。
682+ bool success;
665683
666684 // 如果文件未被标记为已打开,返回 EBADF。
667685 if ((flags & LIBIO_FLAGS_OPEN) == 0)
@@ -678,16 +696,16 @@ int close(int fd)
678696
679697 // 使用原子操作尝试替换标志,确保线程安全。
680698 success = _Atomic_Compare_exchange_uint(
681- &iop->flags, // 要更新的目标变量。
682- &flags, // 当前预期值,会被更新为实际值(若失败)。
683- desired, // 想要写入的新值。
684- ATOMIC_ORDER_ACQ_REL, // 成功时的内存顺序。
685- ATOMIC_ORDER_RELAXED // 失败时的内存顺序。
699+ &iop->flags, // 要更新的目标变量。
700+ &flags, // 当前预期值,会被更新为实际值(若失败)。
701+ desired, // 想要写入的新值。
702+ ATOMIC_ORDER_ACQ_REL, // 成功时的内存顺序。
703+ ATOMIC_ORDER_RELAXED // 失败时的内存顺序。
686704 );
687705
706+ // 成功清除 OPEN 标志,跳出循环。
688707 if (success)
689708 {
690- // 成功清除 OPEN 标志,跳出循环。
691709 break;
692710 }
693711
@@ -699,11 +717,14 @@ int close(int fd)
699717 }
700718
701719 // 调用具体文件系统提供的 close 方法。
702- rc = (*iop->pathinfo.handlers->close_h)(iop); // 关闭文件,通常会执行文件系统特定的清理工作。
720+ // 关闭文件,通常会执行文件系统特定的清理工作。
721+ rc = (*iop->pathinfo.handlers->close_h)(iop);
703722
704- rtems_libio_free(iop); // 释放 I/O 对象资源,回收到 I/O 对象池中以供复用。
723+ // 释放 I/O 对象资源,回收到 I/O 对象池中以供复用。
724+ rtems_libio_free(iop);
705725
706- return rc; // 返回关闭操作的结果,通常为 0 表示成功,-1 表示失败(并设置 errno)。
726+ // 返回关闭操作的结果,通常为 0 表示成功,-1 表示失败(并设置 errno)。
727+ return rc;
707728}
708729```
709730
@@ -718,17 +739,22 @@ ssize_t read(
718739 size_t count // 期望读取的字节数。
719740)
720741{
721- rtems_libio_t *iop; // 指向文件描述符对应的 I/O 对象结构体。
722- ssize_t n; // 实际读取的字节数或错误代码。
742+ // 指向文件描述符对应的 I/O 对象结构体。
743+ rtems_libio_t *iop;
744+
745+ // 实际读取的字节数或错误代码。
746+ ssize_t n;
723747
724748 // 检查 buffer 是否为 NULL,防止非法内存访问。
725749 rtems_libio_check_buffer(buffer);
726750
727751 // 检查读取字节数是否为 0 或超出合理范围。
728752 rtems_libio_check_count(count);
729753
730- // 获取对应的 I/O 对象,并检查是否具有可读权限。
731- // 若无效或不可读,则自动设置 errno = EBADF 并返回 -1。
754+ /*
755+ * 获取对应的 I/O 对象,并检查是否具有可读权限。
756+ * 若无效或不可读,则自动设置 errno = EBADF 并返回 -1。
757+ */
732758 LIBIO_GET_IOP_WITH_ACCESS(fd, iop, LIBIO_FLAGS_READ, EBADF);
733759
734760 /*
@@ -741,7 +767,8 @@ ssize_t read(
741767 // 读取完成后释放 I/O 对象(减少引用计数等)。
742768 rtems_libio_iop_drop(iop);
743769
744- return n; // 返回实际读取的字节数,若出错则为负值并设置 errno。
770+ // 返回实际读取的字节数,若出错则为负值并设置 errno。
771+ return n;
745772}
746773```
747774
@@ -756,17 +783,22 @@ ssize_t write(
756783 size_t count // 要写入的字节数。
757784)
758785{
759- rtems_libio_t *iop; // 指向文件描述符关联的 I/O 对象。
760- ssize_t n; // 实际写入的字节数或错误码。
786+ // 指向文件描述符关联的 I/O 对象。
787+ rtems_libio_t *iop;
788+
789+ // 实际写入的字节数或错误码。
790+ ssize_t n;
761791
762792 // 检查 buffer 是否为 NULL,防止非法内存访问。
763793 rtems_libio_check_buffer (buffer);
764794
765795 // 检查写入的字节数是否合理(非零、未超限)。
766796 rtems_libio_check_count (count);
767797
768- // 获取 I/O 对象,并检查是否具有写权限。
769- // 若非法或不可写,则设置 errno = EBADF,并返回 -1。
798+ /*
799+ * 获取 I/O 对象,并检查是否具有写权限。
800+ * 若非法或不可写,则设置 errno = EBADF,并返回 -1。
801+ */
770802 LIBIO_GET_IOP_WITH_ACCESS (fd, iop, LIBIO_FLAGS_WRITE, EBADF);
771803
772804 /*
@@ -778,7 +810,8 @@ ssize_t write(
778810 // 操作完成后释放 I/O 对象(例如减少引用计数)。
779811 rtems_libio_iop_drop (iop);
780812
781- return n; // 返回写入的字节数,失败时为负值并设置 errno。
813+ // 返回写入的字节数,失败时为负值并设置 errno。
814+ return n;
782815}
783816```
784817
@@ -875,7 +908,7 @@ rtems_filesystem_register() 用于在 Rtems 操作系统中注册一个新的文
875908
876909``` c
877910int rtems_filesystem_register (
878- // 文件系统类型字符串,例如 "imfs"、"dosfs" 等。
911+ // 文件系统类型字符串,例如 "imfs"、"dosfs" 等。
879912 const char *type,
880913 // 挂载处理函数指针,用于挂载该类型的文件系统。
881914 rtems_filesystem_fsmount_me_t mount_h)
@@ -886,24 +919,24 @@ int rtems_filesystem_register(
886919 // 计算文件系统类型字符串长度(包含字符串结束符)。
887920 size_t type_size = strlen(type) + 1;
888921
889- // 计算要分配的内存大小:filesystem_node结构体大小 + 文件系统类型字符串大小。
922+ // 计算要分配的内存大小:filesystem_node 结构体大小 + 文件系统类型字符串大小。
890923 size_t fsn_size = sizeof(filesystem_node) + type_size;
891924
892925 // 动态分配内存用于存储新文件系统节点和类型字符串。
893926 filesystem_node *fsn = malloc(fsn_size);
894927
895- // 指向分配内存中,存储类型字符串的位置(紧接在filesystem_node结构体之后 )。
928+ // 指向分配内存中,存储类型字符串的位置(紧接在 filesystem_node 结构体之后 )。
896929 char *type_storage = (char *)fsn + sizeof(*fsn);
897930
898931 // 如果内存分配失败。
899932 if (fsn == NULL)
900- // 设置错误码为“内存不足”,返回-1。
933+ // 设置错误码为“内存不足”,返回 -1。
901934 rtems_set_errno_and_return_minus_one(ENOMEM);
902935
903936 // 将传入的文件系统类型字符串拷贝到刚分配的内存中。
904937 memcpy(type_storage, type, type_size);
905938
906- // 设置节点中的type指针指向存储的类型字符串 。
939+ // 设置节点中的 type 指针指向存储的类型字符串 。
907940 fsn->entry.type = type_storage;
908941
909942 // 设置节点中的挂载处理函数指针。
@@ -929,14 +962,14 @@ int rtems_filesystem_register(
929962 // 释放刚分配的内存。
930963 free(fsn);
931964
932- // 设置错误码为“无效参数”(文件系统类型重复),返回-1。
965+ // 设置错误码为“无效参数”(文件系统类型重复),返回 -1。
933966 rtems_set_errno_and_return_minus_one(EINVAL);
934967 }
935968
936969 // 解锁。
937970 rtems_libio_unlock();
938971
939- // 成功返回0 。
972+ // 成功返回 0 。
940973 return 0;
941974}
942975```
0 commit comments