1.文件描述符文件句柄和打开文件之间的关系
Posted 666QAQ
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了1.文件描述符文件句柄和打开文件之间的关系相关的知识,希望对你有一定的参考价值。
专栏说明
两三个月前试着读过这本书,感觉像啃石头。今天终于又下定决心来啃它,体验比之前好多了。
但是书里的东西,还是比较抽象,一下子看不明白,所以准备对学习过程做个记录。
这是第一篇,以后再碰到难点会继续记录。
起因
p76~p79
76、77草草看过去,不甚求解,只记得p78的一条要点:
两个不同的文件描述符,若指向同一打开文件句柄,将共享同一文件偏移量。因此,如果通过其中一个描述符来修改文件偏移量(由调用read()、write()、或lseek()所致),那么从另一文件描述符中也会观察到这一变化。无论这两个文件描述符分属于不同进程,还是同属于一个进程,情况都是如此。
但是78页又讲到:
仅仅简单地打开results.log文件来两次是远远不够的(第一次在描述符1上打开,第二次在描述符2上打开)。首先两个文件描述符不能共享相同的文件偏移量指针,因此有可能相互覆盖彼此的输出。在这打开的文件不一定就是磁盘文件。
经过
刚看到挺懵逼的。😦
又从头看了一遍,才发现了重点:
- 进程级的文件描述符表(文件描述符)
- 系统级的打开文件表(文件句柄)
- 文件系统的i-node表
这三个东西不是一回事。
看懂这张图很重要
区别在于书上那段话:
在进程A中,文件描述符1和20都指向同一个打开的文件句柄(标号为23)。这可能是通过调用dup()、dup2()或fcntl()而形成的(参见5.5节)。
进程A的文件描述符2和进程B的文件描述符2都指向同一个打开的文件句柄(标号73)。这种情形可能在调用fork()后出现(即,进程A与进程B之间是父子关系),或者当某进程通过UNIX域套接字将一个打开的文件描述符传递给另一个进程时,也会发生(参见61.13.3节)。
此外,进程A的描述符0和进程B的描述符3分别指向不同的打开文件句柄,但这些句柄均指向i-node表中的相同条目(1976),换言之,指向同一文件。发生这种情况是因为每个进程各自对同一文件发起了open()调用。同一个进程两次打开同一文件也会发生类似情况。
结果
看到这里才明白,总之就是三条规则:
- 指向同一文件句柄的文件描述符共享同一文件偏移量(必定也指向同一个i-node条目,也即是同一文件)。
- open()两次打开的描述符不指向同一文件句柄(也就是文件偏移量不相同)。
- dup()、dup2()复制的文件描述符指向同一文件句柄(也就是文件偏移量相同)。
示例
cat tmp.txt
123456789ABCDEFGHIJKLMN
dup()
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
int main(void)
const char fileName[]="tmp.txt";
int fd_1 = open(fileName, O_RDONLY),
fd_2 = dup(fd_1);//copy the fd_1 by dup()
char buf [1024];
ssize_t numRead;
numRead = read(fd_1, buf, 10);
buf[numRead]='\\0';
printf("numRead: %zd\\n",numRead );
printf("%s\\n", buf);
numRead = read(fd_2, buf, 10);
buf[numRead]='\\0';
printf("numRead: %zd\\n", numRead);
printf("%s\\n", buf);
printf("fd_1:%d\\n", close(fd_1));
printf("fd_2:%d\\n", close(fd_2));
result:
numRead: 10
123456789A
numRead: 10
BCDEFGHIJK
fd_1:0
fd_2:0
open()
.../*same as above*/
int fd_1 = open(fileName, O_RDONLY),
fd_2 = open(fileName, O_RDONLY);
//reopen the file
.../*same as above*/
result:
numRead: 10
123456789A
numRead: 10
123456789A
fd_1:0
fd_2:0
初学者,如有理解错误之处,还望大佬多多指正。😃
以上是关于1.文件描述符文件句柄和打开文件之间的关系的主要内容,如果未能解决你的问题,请参考以下文章