【Linux系列】到底什么是文件描述符?

文件描述符

文件描述符已经不陌生了,在一个进程中一个打开的文件就是用一个文件描述符所表征的,可以看作是一个句柄,就是所谓的遥控器。但是这个遥控器到底怎么来控制具体的文件呢?接下来会依此讲解文件描述符背后的在UNIX环境下实现相关的数据结构。

UNIX环境下的文件共享

文件描述符用来表征一个文件,在进程PCB中有着这么一个部分,IO状态信息,说的再具体点,在PCB中存在着一张表,我们可以叫它文件描述符表,也可以叫做打开文件描述符表,这张表每个进程都会有且为进程独有,所以它是进程级的。这张表上的每一个表项都由两个部分组成文件描述符标志以及一个文件指针。其中文件描述符标志也就是我们所使用的文件描述符fd,当然我们也可以将其看做是这张表的下标。这张表长这样。
  【Linux系列】到底什么是文件描述符?_第1张图片

这张表中每一项都有一个文件指针,那么这个指针又指向哪里呢?这就要提到另一张表打开文件表,注意这张表由操作系统管理,且系统中只有唯一一张这样的表,因此这张表是系统级的。这张表中的每一项都存储着一个进程与这个文件相关的一些信息,其中主要分为三个部分:文件状态标志,文件当前偏移量,v-node结点指针。

  文件状态标志就是文件在打开时的状态标志,例如可读,可写,可读写,阻塞等都会记录在其中,这些状态标志也可以使用fcntl函数修改。
  
  文件当前偏移量就是文件指针当前在文件中指向的位置,我们可以用lseek函数修改。
  
  v-node结点指针我们稍后再谈,现在我们要详细讲讲这张表的工作过程。

这张表属于系统级的,系统中任何进程打开任何文件都会在其中添加一个记录项,按照一般情况下来说两个不同的进程打开相同的文件也会在表中创建两个不同的表项,因此两个进程对同一个文件可以有不同的状态标志以及文件当前偏移量。

一个进程中不同的文件描述符所代表的文件描述符表项中的文件指针也该指向不同的打开文件表项,但是在某些情况下文件描述符表中不同表项的指针却又有可能指向系统级打开文件表中的同一个表项。例如我们在fork子进程时,子进程复制父进程PCB中的大部分信息包括IO状态信息时会复制文件描述符表,因此两个不同的进程此时就会打开同一个文件,并且文件指针的指向也不会改变会指向相同的打开文件表表项;在使用dup函数重定向时一个进程中不同文件描述符表项中的文件指针也会指向同一个打开文件表中的表项。
  这张表中的每个表项长这样。
  【Linux系列】到底什么是文件描述符?_第2张图片
  最后还剩一个问题,这个v-node结点指针干嘛用的?v-node节点指针指向v-node节点。那么什么是v-node节点?说到v-node就不得不提起i-node节点,在UNIX操作系统中操作系统管理文件的方式是通过使用v-node和i-node节点的方式进行管理的,每个文件都会有这样的节点用于保存相关的文件信息,例如v-node节点上保存了文件类型,对这个文件进行操作的函数指针以及对应的i-node节点的指针;而i-node节点上保存了文件长度,文件数据存储在磁盘的位置,文件所属者等。这些文件信息平时存储在磁盘上,当一个文件打开时系统会将这些信息读入内存,并且相同的文件的i-node及v-node节点在内存中只会存在一份。这两个节点长这样。
【Linux系列】到底什么是文件描述符?_第3张图片
那么为什么要用两个节点保存这些信息呢?这是为了在一个操作系统上对多文件系统进行支持。把与文件系统无关的文件信息存储在v-node节点上,其余信息存在i-node上,分开存储,这样的系统也叫做虚拟文件系统。而Linux比较特殊,其中没有v-node节点而是用了两个不同的i-node节点,但是结果而言大同小异。

综上所述,把以上数据结构连接起来就构成了一个进程对文件进行控制的完整脉络,进程也就得到了和文件控制有关的所有信息,可见并不是所有文件信息都保存在PCB中的。
  【Linux系列】到底什么是文件描述符?_第4张图片
 对于两个不同的进程打开同一个文件,他们的文件指针可能指向不同的打开文件表项,但是最终都会指向同一个v-node和i-node节点,正如之前所说,相同文件的有关信息在内存中只会存在一份。如下图。
【Linux系列】到底什么是文件描述符?_第5张图片

你可能感兴趣的:(操作系统,linux)