@@ -5,7 +5,7 @@ categories:
55 - 内核层
66abbrlink : 4936fe45
77date : 2025-05-19 12:50:00
8- updated : 2025-05-19 12:50 :00
8+ updated : 2025-05-21 23:00 :00
99---
1010
1111<meta name =" referrer " content =" no-referrer " />
@@ -391,7 +391,7 @@ static int do_open(
391391 // 设置 iop 的文件控制标志,转换 POSIX oflag 为 LibIO 内部标志。
392392 rtems_libio_iop_flags_set(iop, rtems_libio_fcntl_flags(oflag));
393393
394- // 调用底层文件系统驱动的 open 函数打开文件。
394+ // 调用底层文件系统的 open 函数打开文件。
395395 rv = (*iop->pathinfo.handlers->open_h)(iop, path, oflag, mode);
396396
397397 // 如果打开成功。
@@ -543,18 +543,18 @@ rtems_filesystem_eval_path_extract_currentloc(&ctx, &iop->pathinfo);
543543rtems_filesystem_eval_path_cleanup(&ctx);
544544```
545545
546- #### 底层文件系统驱动的 open 函数
546+ #### 底层文件系统的 open 函数
547547
548548拿到所有信息以后,do_open() 函数中调用底层文件系统的 open() 函数真正打开文件:
549549
550550```c
551- // 调用底层文件系统驱动的 open 函数打开文件。
551+ // 调用底层文件系统的 open 函数打开文件。
552552rv = (*iop->pathinfo.handlers->open_h)(iop, path, oflag, mode);
553553```
554554
555555## close 函数
556556
557- close() 函数的源码如下。在前面更改完状态标志位后,还是会进入到底层文件系统驱动的 close_h 函数。
557+ close() 函数的源码如下。在前面更改完状态标志位后,还是会进入到底层文件系统的 close_h 函数。
558558
559559``` c
560560int close (int fd)
@@ -631,3 +631,79 @@ int close(int fd)
631631 return rc; // 返回关闭操作的结果,通常为 0 表示成功,-1 表示失败(并设置 errno)。
632632}
633633```
634+
635+ ## read 函数
636+
637+ read() 函数的源码如下。可以看出除了做了一些检查以外,直接调用了底层文件系统的 read_h() 函数。
638+
639+ ```c
640+ ssize_t read(
641+ int fd, // 文件描述符,标识要读取的文件或设备。
642+ void *buffer, // 指向用户提供的内存缓冲区。
643+ size_t count // 期望读取的字节数。
644+ )
645+ {
646+ rtems_libio_t *iop; // 指向文件描述符对应的 I/O 对象结构体。
647+ ssize_t n; // 实际读取的字节数或错误代码。
648+
649+ // 检查 buffer 是否为 NULL,防止非法内存访问。
650+ rtems_libio_check_buffer(buffer);
651+
652+ // 检查读取字节数是否为 0 或超出合理范围。
653+ rtems_libio_check_count(count);
654+
655+ // 获取对应的 I/O 对象,并检查是否具有可读权限。
656+ // 若无效或不可读,则自动设置 errno = EBADF 并返回 -1。
657+ LIBIO_GET_IOP_WITH_ACCESS(fd, iop, LIBIO_FLAGS_READ, EBADF);
658+
659+ /*
660+ * 正式执行读取操作:
661+ * 调用底层文件系统或设备驱动提供的 read 函数。
662+ * 由 handlers->read_h 函数指针调用完成具体的读取逻辑。
663+ */
664+ n = (*iop->pathinfo.handlers->read_h)(iop, buffer, count);
665+
666+ // 读取完成后释放 I/O 对象(减少引用计数等)。
667+ rtems_libio_iop_drop(iop);
668+
669+ return n; // 返回实际读取的字节数,若出错则为负值并设置 errno。
670+ }
671+ ```
672+
673+ ## write 函数
674+
675+ write() 函数的源码如下。大致逻辑同样同 read 函数。
676+
677+ ``` c
678+ ssize_t write (
679+ int fd, // 文件描述符,表示要写入的目标文件或设备。
680+ const void *buffer, // 用户数据缓冲区的地址。
681+ size_t count // 要写入的字节数。
682+ )
683+ {
684+ rtems_libio_t *iop; // 指向文件描述符关联的 I/O 对象。
685+ ssize_t n; // 实际写入的字节数或错误码。
686+
687+ // 检查 buffer 是否为 NULL,防止非法内存访问。
688+ rtems_libio_check_buffer (buffer);
689+
690+ // 检查写入的字节数是否合理(非零、未超限)。
691+ rtems_libio_check_count (count);
692+
693+ // 获取 I/O 对象,并检查是否具有写权限。
694+ // 若非法或不可写,则设置 errno = EBADF,并返回 -1。
695+ LIBIO_GET_IOP_WITH_ACCESS (fd, iop, LIBIO_FLAGS_WRITE, EBADF);
696+
697+ /*
698+ * 调用底层设备或文件系统提供的写入实现。
699+ * 实际写入的逻辑由 write_h 函数指针指定。
700+ */
701+ n = (*iop->pathinfo.handlers->write_h)(iop, buffer, count);
702+
703+ // 操作完成后释放 I/O 对象(例如减少引用计数)。
704+ rtems_libio_iop_drop (iop);
705+
706+ return n; // 返回写入的字节数,失败时为负值并设置 errno。
707+ }
708+ ```
709+
0 commit comments