文件共享及dup、fcntl函数详解

一、文件共享

1、简介

在介绍dup函数之前,先要说明不同进程共享打开文件。
内核使用三种数据结构表示打开文件,它们之间的关系决定了在文件共享方面一个进程对另一个进程可能产生的影响。
(1)每个进程在进程表中都有一个记录项,记录项中包含一张打开文件描述符表,可将其视为一个矢量,每个描述符占用一项。
(2)内核为所有打开文件维持一张文件表。
(3)每个打开文件(或设备)都有一个v节点结构。
下图为详细介绍:
假设该进程有两个不同的打开文件,一个从标准输入打开,一个从标准输出打开:
这里写图片描述
如果两个独立进程各自打开了同一文件,假定第一个进程在文件描述符3上打开该文件,另一个进程在文件描述符4上打开。在则有如下关系:
这里写图片描述
打开该文件的每个进程都获得各自的一个文件表项,但对一个给定的文件只有一个v节点表项。之所以每个进程都获得自己的文件表项,是因为这可以使每个进程有自己对该文件的当前偏移量。

2、说明

我们现在对上述操作做进一步说明:
下述文件操作函数详情请看文章:这里写链接内容
(1)在完成每个write后,在文件表项中的当前文件偏移量即增加所写入的字节数。如果这导致当前文件偏移量超出了当前文件长度,则将i节点表项中的当前文件长度设置为当前文件偏移量(也就是该文件加长了)
(2)如果用O_APPEND标志打开一个文件,则相应标志位也被设置到文件表项的文件状态标志中。每次对这种具有追加写标志的文件执行写操作时,文件表项中的当前文件偏移量首先会被设置为i节点表项中的文件长度。这就使得每次写入的数据都追加到文件的当前尾端处。
(3)若一个文件用lseek定位到文件当前的尾端,则文件表项中的当前文件偏移量被设置为i节点表项中的当前文件长度。

可能会有多个文件描述符指向同一文件表项。下面我们来了解。

二、复制文件描述符

1、dup和dup2函数

这两个函数都能用来复制一个现有的文件描述符。
函数原型如下:
这里写图片描述

返回值:若成功,返回新的文件描述符。若出错,返回-1。
up返回的新文件描述符一定是当前可用文件描述符中的最小数值。
对于dup2,可以用newfd指定新描述符的值。如果newfd已经打开,则先将其关闭。若newfd等于oldfd,则dup2返回newfd,而不关闭它。

这两个函数返回的新文件描述符与参数oldfd共享同一个文件表项,
假定函数开始执行时,下一个可用的文件描述符是3,执行了newfd=dup(1)操作。
如下图:
这里写图片描述

2、fcntl函数

我们看一下函数原型:
这里写图片描述

复制一个描述符的另一种方法是使用fcntl函数:
调用:
dup(fd);
等效于fcntl(fd,F_DUPFD,0);
而调用
dup2(fd,fd2);
等效于close(fd2); fcntl(fd,F_DUPFD,fd2);
(这种情况下并不完全等同,dup2是一个原子操作)

猜你喜欢

转载自blog.csdn.net/baidu_37964071/article/details/80330556