在linux中有不少种方式共享文件,可是底层原理都是经过描述符表,文件表, v-node表来实现的。接下来主要讲解下这三张表中内容以及彼此之间的关系。在linux内核中,采用Descriptor table,File table,v-node table来表示打开的文件。node
每一个进程都有一个 descriptor table(描述符表),其中的条目指向file table中的一条内容linux
全部被打开的文件都在file table中表示,而且是由进程共享的。file table中的一条内容主要包括文件位置(文件内容的偏移量),在descriptor table中有多少条目指向此数据(reference count),指向v-node的指针。关闭一个描述符就是将reference count 减1,直到reference count的数目为1,才会将descriptor table中的对应条目删除。函数
v-node table也是由全部进程共享的。v-node table中的每一个条目都包含了一个文件的大部份内容,如文件权限,读写时间等等;相似于stat结构中的内容。3d
下面介绍几个例子来具体看下文件共享时,三个表之间的关系指针
下图表示了一个进程打开了两个文件。stdin,stdout,stderr分别表示标准输入,标准输出,标准错误。即fd1标准输出指向文件A,fd3描述符指向文件B code
能够看到file table中的两个条目指向了同一个v-node table中的一个元素 若是咱们对于同一个文件连续调用两次open函数,就能够获得图中所示的关系。因为每一个文件描述符都有其本身的文件位置,因此每一个文件描述符能够读取文件不一样的部分blog
若是对于图1的进程,咱们调用fork函数,则会出现下面的关系 进程
能够看到子进程内的内容彻底是父进程的一份拷贝ip
dup2函数能够进行文件的重定向,好比将标准输出重定向到文件等,这个在咱们平时的开发过程当中常常能够碰到。其函数原型以下:开发
#include <unistd.h> // returns: nonnegative descriptor if OK, -1 on error int dup2(int oldfd, int newfd);
dup2函数将oldfd拷贝到newfd中,覆盖newfd中以前的记录;若是newfd已经打开了,则dup2会将newfd先关闭而后在拷贝。对于图1,咱们执行dup2(4, 1)
, 结果以下所示:
能够看到两个描述符都指向了文件B,文件A已经关闭了,而且文件A对应的file table和v-node table中的条目也已经删除了。文件B的reference count变成了2. 任何写到标准输出的内容都被重定向到文件B中。