在C程序中,文件由文件指针或者文件描述符表示。ISO C的标准I/0库函数(fopen, fclose, fread, fwrite, fscanf, fprintf等)使用文件指针,UNIX的I/O函数(open, close, read, write, ioctl)使用文件描述符。下面重点来说下,文件描述符是如何工作的。

文件描述符相当于一个逻辑句柄,而open,close等函数则是将文件或者物理设备与句柄相关联。句柄是一个整数,可以理解为进程特定的文件描述符表的 索引。先介绍下面三个概念,后面讲下open、close等操作以后,文件和文件描述符产生什么关系,以及fork后文件描述符的继承等问题。

文件描述符表:用户区的一部分,除非通过使用文件描述符的函数,否则程序无法对其进行访问。对进程中每个打开的文件,文件描述符表都包含一个条目。
系统文件表:为系统中所有的进程共享。对每个活动的open, 它都包含一个条目。每个系统文件表的条目都包含文件偏移量、访问模式(读、写、or 读-写)以及指向它的文件描述符表的条目计数。
内存索引节点表: 对系统中的每个活动的文件(被某个进程打开了),内存中索引节点表都包含一个条目。几个系统文件表条目可能对应于同一个内存索引节点表(不同进程打开同一个文件)。
1、举例: 执行myfd = open( "/home/lucy/my.dat", O_RDONLY); 以后,上述3个表的关系原理图如下:

统文件表包含一个偏移量,给出了文件当前的位置。若2个进程同时打开一个文件(如上图A,B)做读操作,每个进程都有自己相对于文件的偏移量,而且读入 整个文件是独立于另一个进程的;如果2个进程打开同一个文件做写操作,写操作是相互独立的,每个进程都可以重写另一个进程写入的内容。
如果上面进程在open以后又执行了close()函数,操作系统会删除文件描述符表的第四个条目和系统文件表的对应条目(若指向它的描述符表唯一), 并对内存索引节点表条目中的计数减1,如果自减以后变为0,说明没有其他进程链接此文件,将索引节点表条目也删除,而这里进程B也在open这个文件,所 以索引节点表条目保留。

2、文件描述符的继承
通过fork()创建子进程时,子进程继承父进程环境和上下文的大部分内容的拷贝,其中就包括文件描述符表。

(1)对于父进程在fork()之前打开的文件来说,子进程都会继承,与父进程共享相同的文件偏移量。如下图所示(0-1-2 表示 标准输入-输出-错误):

系统文件表位于系统空间中,不会被fork()复制,但是系统文件表中的条目会保存指向它的文件描述符表的计数,fork()时需要对这个计数进行维护, 以体现子进程对应的新的文件描述符表也指向它。程序关闭文件时,也是将系统文件表条目内部的计数减一,当计数值减为0时,才将其删除。
(2)相反,如果父进程先进程fork,再打开my.dat,这时父子进程关于my.dat 的文件描述符表指向不同的系统文件表条目,也不再共享文件偏移量(fork以后2个进程分别open,在系统文件表中创建2个条目);但是关于标准输入, 标准输出,标准错误,父子进程还是共享的。

C/C++ 父子进程之间的文件描述符问题的更多相关文章

  1. Linux 进程间传递文件描述符

    文章目录 文件描述符 文件数据结构 共享文件 UNIX域socket实现传递文件描述符 进程间传递打开的文件描述符,并不是传递文件描述符的值.先说一下文件描述符. 文件描述符 对内核来说,所有打开的文 ...

  2. Linux 利用进程打开的文件描述符(/proc)恢复被误删文件

    Linux 利用进程打开的文件描述符(/proc)恢复被误删文件 在 windows 上删除文件时,如果文件还在使用中,会提示一个错误:但是在 linux 上删除文件时,无论文件是否在使用中,甚至是还 ...

  3. 进程间传递文件描述符——sendmsg和recvmsg函数

    先引入一个例子,该程序的目的是子进程向父进程传递文件描述符,并通过该文件描述符读取buf. #include <func.h> int main(){ int fds[2]; pipe(f ...

  4. 进程间传递文件描述符fd

    众所周知,子进程会继承父进程已经打开的文件描述符fd,但是fork之后的是不会被继承的,这个时候是否无能无力了?答应是NO.Linux提供了一个系统调用sendmsg,借助它,可以实现进程间传递文件描 ...

  5. Linux文件描述符与打开文件之间的区别(转载)

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

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

    Linux中的文件描述符与打开文件之间的关系 导读 内核(kernel)利用文件描述符(file descriptor)来访问文件.文件描述符是非负整数.打开现存文件或新建文件时,内核会返回一个文件描 ...

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

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

  8. [转] linux系统文件流、文件描述符与进程间关系详解

    http://blog.sina.com.cn/s/blog_67b74aea01018ycx.html linux(unix)进程与文件的关系错综复杂,本教程试图详细的阐述这个问题. 包括:     ...

  9. Unix系统编程()文件描述符和打开文件之间的关系

    目前学习到的是一个文件描述符对应着一个打开的文件,似乎是对应的关系.但是实际上并不是这样的.多个文件描述符指向同一个打开的文件,是可能的也是必要的.这些文件描述符可以在相同或者不同的进程中打开. 要理 ...

随机推荐

  1. Checkpoint的运行原理和源码实现

    引言 Checkpoint 到底是什么和需要用 Checkpoint 解决什么问题: Spark 在生产环境下经常会面临 Transformation 的 RDD 非常多(例如一个Job 中包含1万个 ...

  2. Incorrect datetime value

    今天在开发库上给一个表添加字段时候,发现居然报错: root@DB 06:14:42>ALTER TABLE `DB`.` user` ADD COLUMN `status_mode` TINY ...

  3. Selenium IDE的一些操作

    1.运行速度过快时,可能出现找不到元素的情况,影响运行结果,将速度调慢慢一些,就可以运行成功. 如果为其他情况找不到元素,则需要另外找原因,有可能元素定位有问题,有可能无该元素. 2.导出录制的脚本为 ...

  4. 3.12 Templates -- Wrting Helpers(编写辅助器)

    一.概述 1. Helpers允许你向你的模板添加超出在Ember中开箱即用的额外的功能.辅助器是最有用的,用于将来自模型和组件的原始值转换成更适合于用户的格式. 2. 例如,假设我们有一个Invoi ...

  5. fatal error C1010: unexpected end of file while looking for precompiled header directive

    在编译VS时候,出现fatal error C1010: unexpected end of file while looking for precompiled head. 问题详细解释:致命错误C ...

  6. onsubmit不起作用的原因

    使用form表单,添加onsubmit="return check()",来实现提交前进行相关验证功能时,有时会出现js函数不起作用的情况, 此时可以检查相应的js函数check( ...

  7. EL表达式判断条件要写在${}内

    由于老没开发框架了,今天提取公共省市县三级联动组件时,使用jsp传参搞了半天才弄出来. 组件代码 $(function(){console.log("${param.init}") ...

  8. 20145330 《网络对抗》逆向及BOF基础实践

    20145330 <网络对抗>逆向及BOF基础实践 1实践说明 本次实践的对象是一个名为pwn1的linux可执行文件. 该程序正常执行流程是:main调用foo函数,foo函数会简单回显 ...

  9. RPC框架yar安装

    官方网站: http://pecl.php.net/package/msgpack http://pecl.php.net/package/yar 先安装 msgpack $ git clone ht ...

  10. MSSQL 重建索引(在线重建、控制最大处理器数 、MAXDOP )

    一.什么情况下需要重建索引 1.碎片过多(参考值:>20%) 索引碎片如何产生,请移步至< T-SQL查询高级—SQL Server索引中的碎片和填充因子> 2.填充度过低(参考值: ...