UNIX系统支持在不同进程间共享打开文件。内核使用3种数据结构表示打开文件,它们之间的关系决定了文件共享方面一个进程对另一个进程可能产生的影响。

  内核维持了3个表,即进程表,文件表和v节点表。具体如下:

  1>每个进程在进程表中都有一个纪录项,记录项中包含一张打开文件描述符表,每个描述符占用一项。与每个文件描述符相关联的是:

  a. 文件描述符标志(close_on_exec);

  b. 指向一个文件表项的指针。

  2>内核为所有打开文件维持一张文件表。每个文件表项包含:

  a. 文件状态标志(读、写、添写、同步和非阻塞等);

  b. 当前文件偏移量;

  c. 指向该文件v节点表项的指针。

  3>每个打开文件(或设备)都有一个v节点(v-node)结构。v节点包含了文件类型和对此文件进行各种操作函数的指针。对于大多数文件,v节点还包含了该文件的i节点(i-node,索引节点),这些信息是在打开文件是从磁盘上读入内存用的。i节点包含了文件的所有者、文件长度、指向文件实际数据块在磁盘上所在位置的指针。(UNIX文件系统中有更多关于i节点的介绍。另,Linux没有使用v节点,而是采用了一个与文件系统相关的i节点和一个与文件系统无关的i节点)

         

                 图1 打开文件的内核数据结构

  上图显示了一个进程对应的3张表之间的关系。该进程有两个不同打开文件:一个文件从标准输入打开(文件描述符0),另一个文件从标准输出打开(文件描述符1)。

  

         

             图2 两个独立进程各自打开同一个文件

  

  一个现有的进程可以调用fork函数创建一个新进程。由fork进程创建的进程称为子进程,frok函数调用一次,返回两次。子进程的返回值是0,父进程的返回是子进程的进程ID。子进程和父进程继续执行fork调用之后的指令。(两个都会执行,但是执行先顺序不定,这取决于内核所使用的调度算法。) 子进程是父进程的副本,如子进程获得父进程数据空间、堆和栈的副本。父进程与子进程并不共享存储空间,但共享正文段。但许多实现并不执行父进程数据的完全副本,而是使用写时复制(Copy-On-Write, COW)技术。

  下列代码中可以看到子进程对变量所做的改变并不影响父进程中该变量的值。

 #include "apue.h"

 ;
 char    buf[] = "a write to stdout\n";

 int
 main(void)
 {
     int        var;
     pid_t    pid;

     ;
     ) != )
         err_sys("write error");
     printf("before fork\n");

     ) {
         err_sys("fork error");
     } ) {
         glob++;
         var++;
     } else {
         sleep();
     }

     printf("pid = %d, glob = %d, var = %d\n", getpid(), glob, var);
     exit();
 }

如果执行该程序,则可得到:

  

  可以看到,第一次为直接执行,输出到标准输出;而第二次重定向到文件了。导致两次执行同样的代码,得到的结果却不同。我们知道,文件I/O函数是不带缓冲的,标准I/O库是带缓冲的。而标准输出连接到终端设备,则它是行缓冲的;否则它是全缓冲的。第一次执行中,printf函数输出到标准输出,缓冲区由换行符冲洗。而重定向到文件时,缓冲区是全缓冲的,在fork调用之前调用了printf一次。但当调用fork时,该行数据仍在缓冲区中,然后再将父进程数据空间复制到子进程中时,该缓冲区数据也被复制到子进程中,此时父进程和子进程各自有个带该行的缓冲区。在exit之前的第二个printf将其数据追加到已有的缓冲区中。当进程终止时,其缓冲区中的内容都被写到相应文件中。

  对上述程序,需要注意的一点是:在重定向父进程的标准输出时,子进程的标准输出也被重定向。fork的一个特性是父进程所有打开文件描述符都复制到子进程中。父进程和子进程每个相同的打开描述符共享一个文件表项。重要的一点是,父进程和子进程共享同一个文件偏移量。

             

转载请注明地址<http://www.cnblogs.com/qiuyi116/p/4322466.html>,谢谢!

  参考《UNIX环境编程》第三版

<UNIX环境高级编程>文件共享及fork函数的更多相关文章

  1. UNIX环境高级编程——sigqueue、sigsuspend函数

    一.sigqueue函数 功能:新的发送信号系统调用,主要是针对实时信号提出的支持信号带有参数,与函数sigaction()配合使用. int sigqueue(pid_t pid, int sig, ...

  2. UNIX环境高级编程——线程和fork

    当线程调用fork时,就为子进程创建了整个进程地址空间的副本.子进程通过继承整个地址空间的副本,也从父进程那里继承了所有互斥量.读写锁和条件变量的状态.如果父进程包含多个线程,子进程在fork返回以后 ...

  3. 《UNIX环境高级编程》笔记--sigaction函数

    sigaction函数的功能是检查或修改指定信号相关联的处理动作,此函数取代UNIX早期版本使用的signal函数. #include<signal.h> int sigaction(in ...

  4. 《UNIX环境高级编程》笔记--read函数,write函数,lseek函数

    1.read函数 调用read函数从文件去读数据,函数定义如下: #include <unistd.h> ssize_t read(int filedes, void* buff, siz ...

  5. UNIX环境高级编程——TCP/IP网络编程 常用网络信息检索函数

    UNIX环境高级编程——TCP/IP网络编程   常用网络信息检索函数 gethostname()   getppername()   getsockname()   gethostbyname() ...

  6. 《UNIX环境高级编程(第3版)》

    <UNIX环境高级编程(第3版)> 基本信息 原书名:Advanced Programming in the UNIX Environment (3rd Edition) (Addison ...

  7. multiple definition of `err_sys' 《UNIX环境高级编程》

    本文地址:http://www.cnblogs.com/yhLinux/p/4079930.html 问题描述: [点击此处直接看解决方案] 在练习<UNIX环境高级编程>APUE程序清单 ...

  8. (二) 一起学 Unix 环境高级编程 (APUE) 之 文件 IO

    . . . . . 目录 (一) 一起学 Unix 环境高级编程 (APUE) 之 标准IO (二) 一起学 Unix 环境高级编程 (APUE) 之 文件 IO (三) 一起学 Unix 环境高级编 ...

  9. (六) 一起学 Unix 环境高级编程 (APUE) 之 进程控制

    . . . . . 目录 (一) 一起学 Unix 环境高级编程 (APUE) 之 标准IO (二) 一起学 Unix 环境高级编程 (APUE) 之 文件 IO (三) 一起学 Unix 环境高级编 ...

随机推荐

  1. Android从入门到精通pdf+书源代码

    不须要积分,免费放送 Android从入门到精通的pdf,入门的好书籍,因为csdn文件大小的限制所以分成了两部分. part1地址:http://download.csdn.net/detail/a ...

  2. MySQL Cluster测试过程中的错误汇总--ERROR 1296 (HY000)等等

    参考资料: http://dev.mysql.com/doc/refman/5.1/en/mysql-cluster-privilege-distribution.html http://www.cl ...

  3. iOS蓝牙中的进制转换

    Bluetooth4.0.jpg 最近在忙一个蓝牙项目,在处理蓝牙数据的时候,经常遇到进制之间的转换,蓝牙处理的是16进制(NSData),而我们习惯的计数方式是10进制,为了节省空间,蓝牙也会把16 ...

  4. iOS开发——高级技术&广告功能的实现

    广告功能的实现 iPhone/iPad的程序,即使是Free的版本,也可以通过广告给我们带来收入.前提是你的程序足够吸引人,有足够的下载量.这里,我将介绍一下程序中集成广告的方法.主要有两种广告iAd ...

  5. PERCONA-TOOLKIT 工具文档

    https://www.percona.com/doc/percona-toolkit/2.2/index.html

  6. 《RESTful Web Services》第一章 使用统一接口

    序言 HTTP是一种应用层协议.SOAP和一些Ajax Web框架都将HTTP作为一种传输信息的协议,难以充分利用HTTP层的基础设施. 1.2 如何保持交互的可见性     可见性是HTTP的一个核 ...

  7. git svn 5点区别

    如果你在读这篇文章,说明你跟大多数开发者一样对GIT感兴趣,如果你还没有机会来试一试GIT,我想现在你就要了解它了. GIT不仅仅是个版本控制系统,它也是个内容管理系统(CMS),工作管理系统等.如果 ...

  8. Maven项目中如何添加日志

  9. C++ (P70—P96)

    1 类的成员默认为私有模型 2 类的声明内不允许对数据成员进行初始化 3 类的成员函数,如果在类外定义,只需在函数类型之前加上inline就为内联函数了,如果在类内定义函数则该函数自动成为内联成员函数 ...

  10. c/c++中动态内存分配处理字符串的细节问题

    #include <stdio.h> #include <stdlib.h> #include <string.h> #include <malloc.h&g ...