Skip to content

Commit 4a441b5

Browse files
committed
read and write
1 parent 9c751b2 commit 4a441b5

File tree

1 file changed

+81
-5
lines changed

1 file changed

+81
-5
lines changed

为了工作/Linux/内核层/Rtems Source Code.md

Lines changed: 81 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ categories:
55
- 内核层
66
abbrlink: 4936fe45
77
date: 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);
543543
rtems_filesystem_eval_path_cleanup(&ctx);
544544
```
545545
546-
#### 底层文件系统驱动的 open 函数
546+
#### 底层文件系统的 open 函数
547547
548548
拿到所有信息以后,do_open() 函数中调用底层文件系统的 open() 函数真正打开文件:
549549
550550
```c
551-
// 调用底层文件系统驱动的 open 函数打开文件。
551+
// 调用底层文件系统的 open 函数打开文件。
552552
rv = (*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
560560
int 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

Comments
 (0)