文件的三个表
内核用三个相关的数据结构来表示打开的文件:
描述符表(descriptor table)。每个进程都有它独立的描述附表,他的表项是由进程打开文件的文件描述符来索引的。每个打开的描述符表项指向文件表中的一个表项。文件表(file table)。打开文件的集合是有一张文件表来表示的,所有的进程共享这张表。每个文件表的表项组成(针对我们的目的)包括当前文件位置、引用计数(reference count)(即当前指向该表项的描述表项数),以及一个指向v-node表中对应表项的指针。关闭一个描述符会减少相应的文件表表项中的引用计数。内核不会删除这个文件表象,直到他的引用计数为零。v-node表(v-node table)。同文件表一样,所有进程共享这张V-NODE表。每个表项包含stat结构中的大多数信息(包括st_mode和st_size成员)
一个实验:
#include <unistd.h>#include <sys/stat.h>#include <stdio.h>#include <fcntl.h>int main(){int fd1,fd2;char c;fd1=open("flag.txt",O_RDONLY,0);fd2=open("flag.txt",O_RDONLY,0);read(fd1,&c,1);read(fd2,&c,1);printf("c=%c\n",c);}
这段程序是两个描述符引用同一个文件,fd1读取一个字的时候fd2文件位置并没有改变,因为每个描述符对于flag.txt都有他自己的文件位置,所以从fd2的读操作会读取flag.txt文件的第一个字节并输出
另一个实验:
#include <unistd.h>#include <sys/stat.h>#include <stdio.h>#include <sys/wait.h>#include <stdlib.h>#include <fcntl.h>int main(){int fd1;char c;fd1=open("flag.txt",O_RDONLY,0);if(fork()==0){read(fd1,&c,1);exit(0);}wait(NULL);read(fd1,&c,1);printf("c = %c\n",c);}
子进程会继承父进程的描述符表,以及所有进程共享的同一个打开文件表。因此,描述符fd在父子进程中都指向同一个打开文件表表项。当子进程读取文件的第一个字节时,文件位置加1.因此,父进程会读取第二个字节.
