linux文件描述符,系统打开文件和i节点的关系

首先区分文件描述符和打开的文件

内核维护了三个数据结构

进程级的文件描述符表(即每个进程一个)

系统级的打开文件表(即该表在整个内核中只有一个)

文件系统的 i-node 表

针对每个进程,内核为其维护一个打开的文件描述符表(open file descriptor table),改表的每一项都记录了单个文件描述符的相关信息,如下:

控制文件描述符的操作的一组标识,目前只定义了一个,即 close-on-exec 标识

对打开文件句柄的引用

系统为所有打开的文件维护了一个系统级别的描述表格(open file description table)。该表的每一项保存了一个已打开的文件的所有相关信息,包括如下内容:

文件指针偏移量 (read()和write()修改,以及lseek()修改)

打开文件的状态标识

文件访问模式

与信号驱动I/O相关的设置

指向 i-node 对象的一个指针

这里有两个概念要区分

一个是文件描述符标识,一个是文件标识。显然,文件描述符标识是标识文件描述符的特性,文件标识是标识文件的特性。close-on-exec是文件描述符的标识。O_APPEND 是文件标识。并且文件描述符标识体现在进程文件描述符表结构中。文件状态标识体现在系统打开文件描述符表中。

每个文件系统都有一个i-node结构,包括如下信息:

文件类型和权限,例如regular file,socket等

该文件持有的所有锁

其他各种特性,比如文件大小,时间戳等等

1. 对同一个文件描述符的读和写位置共享。

测试代码:
char buf[128];
int main(int argc,char *argv[])
{
        char *s = "test";
        int fd = open("test.txt",O_RDWR);
        if(fd == -1)
        {
                perror("open test.txt failure");
                exit(EXIT_FAILURE);
        }

        int readNum = read(fd,buf,3);
        write(fd,s,4);
        if(-1 == close(fd))
        {
                perror("close failure");
                exit(EXIT_FAILURE);
        }
        exit(EXIT_SUCCESS);
}
测试条件,test.txt文件的初始内容为123456789
测试结果:程序执行之后test.txt文件的内容为123test89
分析:

1. 对 test.txt 进行了读写打开

2. 先对test.txt 读3个字节,所以此时fd的偏移量应该是3

3. 接着对fd写4个字节,根据最终的输出结果可以知道此时是从偏移量为3的地方开始写的,所以对于同一个文件描述符来说,读写位置是共享的。

2. 同一个进程多次打开同一个文件

测试代码:
int main(int argc,char *argv[])
{
        char buf[10];
        char *s = "test";
        int fd1 = open("test.txt",O_RDWR);

        int readNum = read(fd1,buf,3);


        int fd2 = open("test.txt",O_RDWR);
        write(fd2,s,4);
}
测试条件,test.txt文件的初始内容为123456789
测试结果:程序执行之后test.txt文件的内容为test56789
分析:

1. 对 test.txt 进行了第一次open操作得到fd1

2. 先通过fd1对test.txt 读3个字节,所以此时fd1所对应的偏移量应该是3

3. 接着对test.txt进行了第二次open操作,得到了fd2,

4. 通过fd2对test.txxt写4个字节,根据最终的输出结果可以知道此时是从偏移量为0的地方开始写的

5. 综上所述,如果对同一个文件打开多次,那么这些文件描述符所对应的内核结构是独立的。

6、从上面的结果也可以看出来,即使是同一个文件,如果我们打开了多次,那么内核也会维护多个打开文件表项。

你可能感兴趣的:(linux文件描述符,系统打开文件和i节点的关系)