当前位置:   article > 正文

open表和closed表_描述符表、文件表与 v-node 表

open表和closed表

描述符表(descriptor table)

描述符 (file descriptor) 代表进程中打开的文件, 通常由 open() 函数返回。 另外 shell 中启动的进程默认会打开 3 个描述符, 分别是:

  • 标准输入, 对应 STDIN_FILENO (值为 0)
  • 标准输出, 对应 STDOUT_FILENO (值为 1)
  • 标准错误, 对应 STDERR_FILENO (值为 2)

每个进程都有自己的描述符表,用以记录进程中所有打开的文件。一个描述符对应于一个打开的文件。

当调用 close() 函数时,系统会回收对应的描述符。

文件表(file table)

所有进程共享一个文件表

文件表记录了被打开文件的一些状态信息, 包括 文件位置引用计数以及指向v-node表的指针等

  • 所有打开的文件都有一个文件位置,表示下一次读或写的起始位置。 seek, read, write 函数都可以修改该文件位置。
  • 所有进程共享同一个文件表。文件表中的一个表项可能会被多个描述符指向,引用计数用来表示当前有多少个描述符指向该文件表表项。当调用 close() 函数时,系统会将描述符对应的文件表表项的引用计数减1,然后如果引用计数已经为0,则系统会删除此文件表表项。

当 shell 启动一个进程时,打开了 3 个描述符,每个描述符都指向了一个文件表表项。如下图:

19384d32a3bff5a2a2411738b7e2187e.png

当程序调用 fork() 函数时, 则会出现(不同进程的)多个描述符对应于同一个文件表表项的情况:

  1. void main() {
  2. int fd = open(name, O_RDONLY, 0);
  3. fork();
  4. // ...
  5. }

在 fork() 调用返回之后, 文件表和描述符表的关系如下:

9080bb422d3de41c7b09f7dff832202c.png

这里再介绍一个 dup2() 函数:

int dup2(int oldfd, int newfd);

dup2 函数用 oldfd 的内容替换掉 newfd 的内容。如果 newfd 是打开的,则会再替换之前先关闭 newfd。(思考一下,系统的重定向可能就是用这个函数实现的呢)

当程序调用 dup2 时,也会出现(同一个进程中的)多个描述符指向同一个文件表表项的情况:

  1. void main() {
  2. int fd = open(name, O_RDONLY, 0);
  3. dup2(fd, STDOUT_FILENO);
  4. }
  5. // ...

在 dup2() 调用返回之后, 文件表和描述符表的关系如下:

6a926ac5e1be2369e378bc1cb87a617b.png

v-node 表(v-node table)

所有进程共享同一个 v-node 表

一个 v-node 表的表项对应于一个文件。它记录了文件的元数据信息。包括文件权限,文件大小, 文件类型等信息。

v-node 中的一个表项可能被多个文件表表项指向。

当对同一个文件调用多次 open() 函数,那么会产生多个文件表表项,但是只有一个 v-node 表表项。 如下面的程序:

  1. int fd1 = open("hello.txt", O_RDONLY, 0);
  2. int fd2 = open("hello.txt", O_RDONLY, 0);

它只有一个 v-node 表项,但却有两个描述符表表项和两个文件表表项:

9920812073abc377e74c005b8334afaf.png

参考书籍: 《深入理解计算机系统》

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/你好赵伟/article/detail/889774
推荐阅读
相关标签
  

闽ICP备14008679号