进程如何维护打开的文件

在进程的执行过程中会打开一系列文件,那么进程又是如何记录文件的状态呢?
 
内核使用三种数据结构来表示一个记录项,弄清它们间的关系对于了解文件共享方面的知识很有帮助
进程如何维护打开的文件

1. 每个进程在进程表中都有一个记录项,记录项中包含有一张打开文件描述表,每个描述符占有一项。与每个文件描述符相关联的是:
   + 文件描述符标志
   + 指向一个文件表的指针
2. 内核为所有打开文件维持一张文件表,每个文件表项包含:
   + 文件状态标志
   + 当前文件偏移量
   + 指向该文件V节点表项的指针
3. 每个打开文件都有一个v节点结构(Linux中使用i节点),v节点包含了文件类型和对此文件进行各种操作的函数的指针。对于大多数文件,v节点还包含了该文件的i节点(i-node索引节点)。这个信息都是在打开文件的时候从磁盘上读入内存的,i节点包含了文件的所有者、文件长度、文件所在的设备、指向文件实际数据块在磁盘上所在位置的指针等。
 
Linux没有使用v节点,而是使用了通用的节点结构,虽然两种实现有所不同,但在概念上v节点和i节点是一样的,两者都指向文件系统特有的i节点结构。
 
当在两个进程中同时打开同一个文件时,每个进程表中都有一个记录项,都有自己的文件描述符和指向文件表的指针,而文件表中的v节点指针指向同一个v节点。
进程如何维护打开的文件

图中的两个进程分别在文件描述符3和4上打开同一文件,对于一个给定文件只有一个v节点表项,每个进程都有自己的文件表项的理由是:每个进程都拥有自己对该文件的当前偏移量。
 
当使用dup函数或者fork之后,可能有多个文件描述符指向同一文件表项。在fork之后父子进程对于每一个打开文件描述符共享同一个文件表项。由于共享文件表项,因此拥有同一当前文件偏移量,以下实例:
 
子进程共享所有父进程打开的文件,它们的文件描述符都指向同一个文件表项:
进程如何维护打开的文件

首先在文件描述符上打开指定文件,然后调用dup()函数,使得文件描述符4也指向对应文件,它们也共享文件表,因此具有相同的文件偏移量
进程如何维护打开的文件

下边用程序来验证上图中的情况
 
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
 
int main()
{
    FILE * fp1, * fp2;
    int fd1, fd2;
    if((fd1 = open("in", 2)) < 0)
    {
        printf("open error\n");
        exit(1);
    }
    lseek(fd1, 10, SEEK_SET);  
   
    fd2 = dup(fd1);            
    lseek(fd1, 20, SEEK_SET);  
    lseek(fd2, 30, SEEK_SET);  
    fp1 = fdopen(fd1, "r");    
    fp2 = fdopen(fd2, "r");
    printf("%d %d %d %d\n", fd1, fd2, ftell(fp1), ftell(fp2));
    return 0;
}
打印结果为:30 30,可见两个文件描述符对应的是同一个文件表,具有相同的文件偏移量
 
复制一个描述符的另一种方法时fcntl函数,调用dup(filedes),等效于fcntl(filedes, F_DUPFD, 0);
而调用dup2(filedes, filedes2);等效于close(fildes2); fcntl(filedes, F_DUPFD, filedes2);
原文地址:https://www.cnblogs.com/qianye/p/2786362.html