Skip to content

Latest commit

 

History

History
70 lines (57 loc) · 2.67 KB

10.6.md

File metadata and controls

70 lines (57 loc) · 2.67 KB

10.6 共享文件

在Unix中,可以用许多不同的方式来共享文件,这一节我们来浅析内核是怎么表示打开的文件的

内核三个数据结构

  1. 描述符表
    每个进程都有它独立的描述符表,它的表项是由进程打开的文件描述符来索引,每个打开的描述符表项指向文件表中的一个表项

  2. 文件表
    打开文件的集合是由一张文件表来表示,所有的进程共享这张表

  3. v-node表
    所有的进程进程共享这张表,每个表项包含stat结构的大多信息

打开不同的文件

不同的文件被打开之后,得到不同的文件描述符,放在这个进程描述符表中。在文件表中,也会有不同的文件表项,这个表项记录有当前的文件位置,引用计数和一个指向 v-node表中对应表项的指针。这样,不同的文件被打开,对应进程描述符表中的不同描述符,然后对应所有进程中的文件表,文件表中又对应着不同的v-node表项

同一个文件被打开多次

同一个文件被打开多次之后,产生多个文件描述符,对应文件表中的多个表项,而这些表项中的记录却指向同一个v-node表项

父子进程共享文件

在fork之后,子进程复制了父进程的描述符表(每个进程一个),如果父进程已经有打开的 文件,子进程就会继承下来,父子进程就拥有共同的文件表项,所以v-node表项相同

练习题10.2:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
int main()
{
    int fd1,fd2;
    char c;
    //同一个文件,打开两次,得到不同的文件描述符
    fd1 = open("footbar.txt",O_RDONLY,0);
    fd2 = open("footbar.txt",O_RDONLY,0);
    //对应不同的文件表,不同的文件位置,但指向同一个v-node表项
    read(fd1, &c, 1);
    read(fd2, &c, 1);
    printf("c=%c\n", c); //输出f
    exit(0);
}

练习题10.3:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/wait.h>
int main()
{
    int fd;
    char c;
    fd = open("footbar.txt",O_RDONLY,0);
    if( fork() == 0) //子进程 继承了父进程的文件表项
    {
        read(fd, &c, 1); //子进程读取一个字符
        exit(0);
    }
    //父进程和子进程文件描述符相同,共享了文件表项,共享文件操作的位置
    wait(NULL);       
    read(fd, &c, 1);  //父进程继续读取一个字符
    printf("c=%c\n", c);  //输出o
    exit(0);
}