在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. Linux安装rpm包时报错Header V3 DSA/SHA1 Signature, key ID 1d1e034b: NOKEY解决办法

    这是因为yum安装了旧版本的GPG key造成的,解决办法: rpm --import /etc/pki/rpm-gpg/RPM* Header V3 DSA/SHA1 Signature, key ...

  2. mysql查询表和字段的注释

    1,新建表以及添加表和字段的注释.   create table t_user(        ID INT(19) primary key auto_increment  comment '主键', ...

  3. redhat 5 samba配置

    1.检查安装包 #rpm –qa | grep samba 必须有以下安装结果 samba-3.0.25:samba-common-3.0.25:samba-client-3.0.25:samba-s ...

  4. mono安装

    linux上的DotNET,安装mono 当前,在Linux系统上架设ASP.NET网站.建设WEB应用工程项目已经在国内流行起来,而“Mono+Jexus”架构模式是Linux承载ASP.NET企业 ...

  5. 自定义查询语句SpringData

    虽然官方的API中给我们提供了很多关键字的查询,但是还是不够灵活,因为我们在项目中,会遇见奇葩的业务,我们需要用SpringData中的一个@Query注解. 使用@Query自定义查询 这种查询可以 ...

  6. Linux_Chrome出现Adobe Flash Player is out of date解决方法

    在安装Google的Chrome后都有出现Adobe Flash Player is out of date的问题. Chrome浏览器用的播放器插件是PepperFlashPlayer.而且是内置的 ...

  7. ZOJ Monthly, March 2018 Solution

    A - Easy Number Game 水. #include <bits/stdc++.h> using namespace std; #define ll long long #de ...

  8. validform校验框架不显示错误提示

    今天做前端的校验,发现validform这个框架在项目中有,于是就网上搜索一下,开始使用,网上说,嗯,只写一句代码就可以用啦 $("#itemForm").Validform(); ...

  9. MVC中定时发布二维码邮件

    发布邮件 查看第一个方法就可以了,第二个跟这个无关 using System; using System.Collections.Generic; using System.Linq; using S ...

  10. Ubuntu server 禁止显示器休眠

    Linux不让显示器休眠的方法 # setterm -blank # setterm -blank n (n为等待时间)