文件描述符与打开文件的关系

原创 2015年11月19日 10:10:50

所有执行I/O操作的系统调用都以文件描述符,即一个非负整数来指代所打开的文件。文件描述符可以用来表示所有类型的已打开文件。同时,多个文件描述符可以指向同一个打开文件,因为有在不同进程中打开同一个文件的需求。

那么,系统是如何维护硬盘文件与文件描述符之间的联系呢?

要理解具体的情况如何,需要查看由内核维护的3个数据结构:

  • 进程级的文件描述符
  • 系统级的打开文件表
  • 文件系统的i-node表
针对每个进程,内核为其维护打开文件的描述符(open file descriptor)表。该表的每一项都记录了单个文件描述符的相关信息,如下所示:
  • 控制文件描述符操作的一组标志(目前仅定义了一个,即close-on-exec标志)
  • 对打开文件句柄的引用
内核对所有打开的文件维护一个系统级的描述表格(open file description table)。也叫打开文件表(open file table),表中的每一项称为打开文件句柄(open file handle)。一个打开文件句柄存储了与一个打开文件相关的全信息,如下:
  • 当前文件偏移量(调用read()和write()时更新,或使用lseek()直接修改)
  • 文件的访问模式(如调用read()时设置的只读模式、只写模式等)
  • 与信号驱动I/O相关的设置
  • 对该文件i-node对象的引用
同时,文件系统又会对每个存储其上的文件建立一个i-node表。这里只给出i-node表的信息:
  • 文件类型(如常规文件、套接字或FIFO)和访问权限
  • 一个指针,指向该文件所持有的的锁的列表
  • 文件的各种属性,包括文件大小以及不同类型操作相关的时间戳
下图展示了这3个数据结构之间的关系。在下图中,两个进程拥有诸多打开 的文件描述符:



在进程A中,文件描述符1和20都指向同一个打开的文件句柄23,这可能是通过调用dup、dup2或fcntl形成的。
进程A的文件描述符2和进程B的文件描述符2都指向同一个打开的文件句柄73,这可能是调用fork之后出现的。或者某进程通过UNIX域套接字将一个打开的文件描述符传递给另一个进程。
此外,进程A的文件描述符0和进程B的文件描述符3分别指向不同的打开文件句柄,但这些打开文件句柄指向同一个i-node表中的相同条目。可能是两个进程各自对同一个文件调用open打开。同时,在一个进程中两次打开同一个文件,也会出现这种情况。
这里我们可以得到一些结论:
  1. 两个不同的文件描述符,若指向同一个文件打开句柄,将共享同一文件的偏移量。因此,如果通过其中一个文件描述符来修改文件偏移量(调用open、write、lseek),那么从另一个文件描述符中也会得到相应的改变。不管这两个文件描述符是分别属于同一进程还是不同的进程;
  2. 要获取和修改打开的文件标志(如O_APPEND、O_NONBLOCK等),可以执行fcntl()的F_GETFL和F_SETFL操作,其对作用域的约束与上一条类似;
  3. 相比之下,文件描述符标志(close-on-exec标志)为进程和文件描述符所私有,对这一标志的修改将不会影响同一进程或不同进程中的其他文件描述符。
下面给出具体的实例验证上面的讨论。
fd1=open(file,O_CREAT | O_RDWR | O_TRUNC,S_IRUSR | S_IWUSR);
fd2=dup(fd1);
fd3=open(file,O_RDWR);
write(fd1,"hello",6);
write(fd2,"world",6);
lseek(fd2,0,SEEK_SET);
write(fd1,"HELLO",6);
write(fd3,"yellow",6);

上面的代码中有三个文件描述符,都是打开同一个文件,即共享同一个i-node项。不同的是fd2通过调用dup复制文件描述符fd1,因此fd1与fd2共享同一个文件打开句柄。fd3是同一个进程中另一个open操作,因此和fd1对比,两个文件描述符指向不同的文件打开句柄,但指向同一个i-node项目。下图展示了它们的关系:


因此,对fd1和fd2的open、write、lseek等操作会使文件偏移量发生改变。fd1写入“hello”之后,文件偏移量变为6,fd2写入时在6之后写入,此时文件中的内容是“helloworld”;

当fd2调用lseek改变文件偏移量为0,之后fd1写入文件,是在偏移量为0的基础上写入,因此覆盖最初的6字节,文件内容变为“HELLOworld”;对于fd3,因为与fd1和fd2指向不同的文件打开句柄,因此fd1和fd2的操作不影响fd3指向的文件打开句柄的文件偏移量,所以fd3写入时会覆盖最初的6字节,此时文件内容变为“yelloworld”。

程序运行结果如下:


结果证实了我们的讨论。

linux 可打开的文件描述符数

一个进程可同时打开的文件个数是有限的,这个限制是在/etc//security/limits.conf文件中设置的。例如要设置用户test的一个进程可最大打开的文件数为2048,在该文件里新增加一行:...
  • boshuzhang
  • boshuzhang
  • 2016年04月15日 11:12
  • 474

每天进步一点点——Linux中的文件描述符与打开文件之间的关系

快速理解文件描述符与进程打开文件之间的关系
  • cywosp
  • cywosp
  • 2014年08月31日 22:53
  • 68133

Linux最大打开文件描述符数

系统最大打开文件描述符数:/proc/sys/fs/file-max 查看 $ cat/proc/sys/fs/file-max 186405 设置 # echo 1000000 >/proc...
  • SuperChanon
  • SuperChanon
  • 2013年10月28日 19:34
  • 31728

UNIX再学习 -- 文件描述符

在 UNIX/Linux 系统中,一切皆文件,这句话想必都有听过。对于文件的操作几乎适用于所有的设备,这也就看出了文件操作的重要性了。在C语言再学习部分有讲过标准I/O文件操作,参看:C语言再学习 -...
  • qq_29350001
  • qq_29350001
  • 2017年03月23日 10:07
  • 3057

Linux查看进程打开多少文件描述符命令-lsof

lsof简介 lsof(list open files)是一个列出当前系统打开文件的工具。在linux环境下,任何事物都以文件的形式存在,通过文件不仅仅可以访问常规数据,还可以访问网络连接和硬件。所...
  • zlzlei
  • zlzlei
  • 2012年07月09日 18:17
  • 29282

文件描述符的本质

1. 文件描述符的本质是数组元素的下标 右侧的表称为i节点表,在整个系统中只有1张。该表可以视为结构体数组,该数组的一个元素对应于一个物理文件。 中间的表称为文件表,在整个系统中只有1张。该表...
  • u013078669
  • u013078669
  • 2016年04月17日 11:40
  • 2497

Linux查看进程打开多少文件描述符命令-lsof

转自:http://blog.csdn.net/zlzlei/article/details/7730253 lsof简介 lsof(list open files)是...
  • csCrazybing
  • csCrazybing
  • 2017年04月27日 11:36
  • 937

文件描述符与文件对象的关系

转载请说明出处:http://blog.csdn.net/cywosp/article/details/38965239 概述 在Linux系统中一切皆可以看成是文件,文件又可分为:普通文件、目录文...
  • a675311
  • a675311
  • 2015年10月26日 15:36
  • 699

文件描述符、文件描述符表、打开文件表、目录项、索引节点之间的联系

文件描述符、文件描述符表、打开文件表、目录项、索引节点之间的联系如下图所示:     每个进程在PCB(Process Control Block)中都保存着一份文件描述符表,文件描述符...
  • u014379540
  • u014379540
  • 2016年12月04日 20:10
  • 770

linux 进程文件 文件描述符

转载自:Jezze 、辉仔 url:http://www.cnblogs.com/Jezze/archive/2011/12/23/2299861.html          http://blo...
  • houliang120
  • houliang120
  • 2014年10月07日 14:22
  • 3196
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:文件描述符与打开文件的关系
举报原因:
原因补充:

(最多只允许输入30个字)