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

原创 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中的文件描述符与打开文件之间的关系

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

Linux中的文件描述符与打开文件之间的关系 :http://blog.csdn.net/cywosp/article/details/38965239

[置顶] 每天进步一点点——Linux中的文件描述符与打开文件之间的关系 分类: Linux 2014-08-31 22:53 4170人阅读 评论(0) 收藏 举报 lin...

文件描述符和文件表项

同一进程内: 多个fd可以指向同一个文件表项。(只有dup才会出现这种情况) 多次open出同一个文件,会出现多个文件描述符和多个文件表项,它们的文件偏移量显然是不同步的。 多个文件表项可指向同一个i...

linux下文件描述符的介绍

当某个程序打开文件时,操作系统返回相应的文件描述符,程序为了处理该文件必须引用此描述符。所谓的文件描述符是一个低级的正整数。最前面的三个文件描述符(0,1,2)分别与标准输入(stdin),标准输出(...

Linux中的文件描述符与打开文件之间的关系

出处:http://blog.csdn.net/cywosp/article/details/38965239 1. 概述     在Linux系统中一切皆可以看成是文件,文件又可分为:普通文...

Linux中的文件描述符与打开文件之间的关系

转载请说明出处:http://blog.csdn.net/cywosp/article/details/389652391. 概述    在Linux系统中一切皆可以看成是文件,文件又可分为:普通文件...

Linux中的文件描述符与打开文件之间的关系

内核(kernel)利用文件描述符(file descriptor)来访问文件。文件描述符是非负整数。打开现存文件或新建文件时,内核会返回一个文件描述符。读写文件也需要使用文件描述符来指定待读写的文件...

Linux中的文件描述符与打开文件之间的关系

1. 概述     在Linux系统中一切皆可以看成是文件,文件又可分为:普通文件、目录文件、链接文件和设备文件。文件描述符(file descriptor)是内核为了高效管理已被打开的文件所创...

linux c中的文件描述符与打开文件之间的关系

转载请说明出处:http://blog.csdn.net/cywosp/article/details/38965239 1. 概述     在Linux系统中一切皆可以看成是文件,文件又可分...

Linux中的文件描述符与打开文件之间的关系

转载地址:http://blog.csdn.net/cywosp/article/details/38965239  向原作者致敬! 1. 概述     在Linux系统中一切皆可以看成是...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

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