zoukankan      html  css  js  c++  java
  • 文件描述符表、文件表、索引结点表

    进程打开一个文件,会与三个表发生关联,分别是:文件描述符表、文件表、索引结点表。

    当同一个进程对同一个文件多次使用open时;对一个文件描述符调用dup函数;父进程使用fork创建一个子进程,子进程和上面三个表的关系;当子进程调用exec函数,子进程和上三个表的关系又发生了什么变化;不同的进程打开同一个文件,那么这些进程又是以怎么样的形式相关联。本文将解释这些问题。

    文件描述符表、文件表、索引结点表存放地点

    每个进程都有一个属于自己的文件描述符表。

    文件表存放在内核空间,由系统里的所有进程共享。

    索引结点表也存放在内核空间,由所有进程所共享。

    了解这个些表的存放位置很重要。

    三个表的作用

    文件描述符表:该表记录进程打开的文件。它的表项里面有一个指针,指向存放在内核空间的文件表中的一个表项。它向用户提供一个简单的文件描述符,使得用户可以通过方便地访问一个文件。

    当进程使用open打开一个文件时,内核就会在这个表中添加一个表项。如果对同一个文件打开多次,那么将有多个表项。使用dup时,也会增加一个表项。

    文件表:文件表保存了进程对文件读写的偏移量。该表还保存了进程对文件的存取权限。比如,进程以O_RDONLY方式打开文件,这将记录到对应的文件表表项中。

    索引结点表:在文件系统中,也是有一个索引结点表的。如下图所示:

     

    这两个索引结点表有千丝万缕的关系。因为内存中的索引结点表的每一个表项都是从文件系统中读入的,并且两个索引结点表有一对一的关系。所以,内存中的索引结点表的每一个表项都对应一个具体的文件。

    上面所说的三个表的功能,使得三个表紧密地联系在一起,文件描述符表项有一个指针指向文件表表项,文件表表项有一个指针指向索引结点表表项。

    不同的进程打开同一个文件

    不同的进程打开同一个文件,那么他们应该有各自对应的文件表表项。因为文件表表项记录了进程读写文件时的偏移量和存取权限。多个进程不可能共享一个文件偏移量。另外他们各自打开文件的权限也可能是不同的,有的是为了读、有的为了写,有的为了读写。所以,他们应该有不同的文件表表项。

    此外,因为是同一个文件,所以,多个进程会共享同一个索引结点表项。即他们的文件表表项指针会指向同一个索引结点

    最终,如下图所示:

     

    使用dup函数复制一个文件描述符

    dup函数是用来复制一个文件描述符的。点击这个链接可以看到,复制得到的文件描述符和原描述符共享文件偏移量和一些状态。所以dup的作用仅仅是复制一个文件描述符表项,而不会复制一个文件表表项。

    于是使用dup函数后,有下图:

     

    dup函数是一个很重要的函数。平时我们在shell里面通过 >  来进行重定向,就是通过dup函数来实现的。

    同一个进程多次打开同一个文件

    每打开一次同一个文件,内核就会在文件表中增加一个表项。这是因为每次open文件时使用了不同的读写权限,而读写权限是保存在文件表表项里面的。

    所以,效果图如下所示:

     

    父进程使用fork创建子进程

    由于fork一个子进程,子进程将复制父进程的绝大部分东西(除了进程ID、进程的父进程ID、一些时间属性、文件锁)。所以子进程复制了父进程的整个文件描述符表。

    结果如下图所示:

     

    进程调用exec后,文件描述符的保留情况

    我们经常会在shell中,输入 < 进行标准输入重定向。比如$wc < test.c

    其大致的实现如下:

    if(fork()==0)//child process

    {

    close(0); //关闭键盘这个标准输入

    open(inputFile, O_RDONLY); //返回的文件描述符是最小的未使用的整数,此次就是0,实现了重定向

    exec(); //执行exec

    }

    从上面的例子可以看到执行exec后,文件描述符是会保留的。但有时,可能一个进程有很多个文件描述符,执行exec后,都用不着了。那么此时,应该关闭它。这涉及到一个close-on-exec概念,就是在执行exec时,close(关闭)文件描述符。在默认情况下,执行exec是不关闭的。这里有一个系统调用fcntl可以关闭之。

    它的原型为:

    int fcntl(int fd,int cmd, … /* int arg */);

    第一个参数是文件描述符,第二个参数用来指定是要进行的操作。第三个参数依赖于第二个参数

    与本文相关的是操作是 F_GETFD和F_SETFD。其分别用来获取close-on-exec,设置close-on-exec标识的值。

     可以通过fcntl(fd, F_SETFD, 1);来关闭文件描述符。

    即参数arg为0时,不关闭;为1时关闭。

      参考:《UNIX环境高级编程》、《UNIX操作系统设计》

  • 相关阅读:
    mysq 日期相减
    说说时间观与时间管理——北漂18年(71)
    ionic之切换开关
    ionic之单选框
    SELECT ... LOCK IN SHARE MODE和SELECT ... FOR UPDATE locks在RR模式下可以看到最新的记录
    14.5.2.3 Consistent Nonlocking Reads 一致性非锁定读
    14.5.2.2 autocommit, Commit, and Rollback
    14.5.2 事务隔离级别
    对于唯一索引使用唯一条件搜索, InnoDB 只锁定找到的index record,不是它之前的区间
    mysql explain 解释
  • 原文地址:https://www.cnblogs.com/guxuanqing/p/13377422.html
Copyright © 2011-2022 走看看