【原创】《Linux高级程序设计》杨宗德著- 进程管理与程序开发 - fork和vfork函数

 

【原创】《Linux高级程序设计》杨宗德著- 进程管理与程序开发 - fork和vfork函数

 

1. 创建进程

fork函数调用成功后,其子进程会复制父进程的几乎所有信息(除PID等信息),主发复制父亲进程的代码段、数据段、BSS、堆、栈(关于进程结构参阅本书第3章)、打开的文件描述符(但共用同一个文件表项)。另外,子进程从父进程继承下列属性:实际用户/组号、有效用户/组号以及保留的用户/组号、进程组号、环境变量、对文件的执行时关闭标志、信号处理方式设置、信号掩码、当前工作目录、根目录、文件模式创建掩码、文件大小限制等信息。
代码实例:

/*************************************************************************
	> File Name: fork_basic.c
	> Author: Geng
	> Mail: genglut@163.com
	> Created Time: Thu 30 Oct 2014 10:19:00 PM CST
 ************************************************************************/

#include<stdio.h>
#include<unistd.h>
#include<sys/types.h>
int main(int argc,char *argv[])
{
	pid_t pid;
	if((pid=fork())==-1)
		printf("fork error");
	printf("Geng!\n");
	return 0;
}

运行结果:

$ ./fork_basic 
Geng!
Geng!

从运行结果可以看出,fork函数后的代码在子进程中也被执行。实际上,其他代码也在子进程的代码段中,只是子进程执行位置为fork返回的位置,其之前的代码无法执行罢了。

2. 子进程对父进程文件流缓冲区的处理

在创建子进程时,子进程的用户空间将复制父进程的用户空间所有信息,显然,也包含流缓冲区的内容。如果流缓冲区中有临时信息,则同样复制到子进程的用户空间流缓冲区中。

示例代码如下:

/*************************************************************************
	> File Name: streamfork.c
	> Author: Geng
	> Mail: genglut@163.com
	> Created Time: Thu 30 Oct 2014 10:36:05 PM CST
 ************************************************************************/
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>

int main(int argc,char *argv[])
{
	pid_t pid;
	printf("before fork,have enter\n");
	printf("before fork,no enter:pid=%d\t",getpid());
	pid=fork();
	if(pid==0)
		printf("\nchild,after fork:pid=%d\n",getpid());
	else
		printf("\nparent,after fork:pid=%d\n",getpid());
}

运行结果:

$ ./a.out 
before fork,have enter
before fork,no enter:pid=5397	
parent,after fork:pid=5397
before fork,no enter:pid=5397	
child,after fork:pid=5398

从运行结果可以看出,如果流缓冲区中有临时信息,则同样复制到子进程的用户空间流缓冲区中。

3. 子进程对父进程打开的文件描述符的处理

fork函数创建子进程后,子进程将复制父进程的数据段、BSS段、代码段、堆空间、栈空间和文件描述符,而对于文件描述符关联的内核文件表项(即struct file结构),则是采用共享的方式。

示例代码如下:

/*************************************************************************
	> File Name: datah.c
	> Author: Geng
	> Mail: genglut@163.com
	> Created Time: Thu 30 Oct 2014 11:20:37 PM CST
 ************************************************************************/

#include <sys/types.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <stdlib.h>
int main(int argc,char *argv[])
{
    pid_t pid;
    int fd;
    int i=1;
    int status;
    char *ch1="hello";
    char *ch2="world";
    char *ch3="IN";
    if((fd=open("test.txt",O_RDWR|O_CREAT,0644))==-1)
    {
	perror("parent open");
	exit(EXIT_FAILURE);
    }
    if(write(fd,ch1,strlen(ch1))==-1)
    {	 
	perror("parent write");
	exit(EXIT_FAILURE);
    }
    
    if((pid=fork())==-1)
    {
	perror("fork");
	exit(EXIT_FAILURE);
    }
    else if(pid==0)
    {
	i=2;	
	printf("in child\n");
	printf("i=%d\n",i);
	if(write(fd,ch2,strlen(ch2))==-1)
	    perror("child write");
	return 0;
    }
    else
    {
	sleep(1);
	printf("in parent\n");
	printf("i=%d\n",i);
	if(write(fd,ch3,strlen(ch3))==-1)
	    perror("parent,write");
	wait(&status);
	return 0;
    }
}

运行结果:

$ ./a.out 
in child
i=2
in parent
i=1
$ cat test.txt 
helloworldIN

通过文件test.txt可以看出,父子进程共同对同一文件操作,且写入数据不交叉覆盖,说明父子进程共享文件偏移,因此,共享文件表项。

对于变量i,在子进程中进行了第二次赋值(i=2),其结果为2,而父进程中i的值不变,显然,父子进程各自拥有这一变量的副本,互不影响。

4. vfork测试全局数据段与BSS段的使用策略

fork和vfork有一定的区别,fork是复制一个父进程的副本,拥有自己独立的代码段、数据段及堆栈空间。而vfork是共享父进程的代码及数据段。

示例程序:

#include<unistd.h>
#include<error.h>
#include<sys/types.h>
#include<stdio.h>
#include<stdlib.h>
int glob=6;
int main()
{
	int var;
	pid_t pid;
	var=88;
	printf("in beginning:\tglob=%d\tvar=%d\n",glob,var);
	if((pid=vfork())<0)
	{
		perror("vfork");
		exit(EXIT_FAILURE);
	}
	else if(pid==0)
	{
		printf("in child,modify the var:glob++,var++\n");
		glob++;
		var++;
		printf("in child:\tglob=%d\tvar=%d\n",glob,var);
		_exit(0);
	}
	else
	{	
		printf("in parent:\tglob=%d\tvar=%d\n",glob,var);
		return 0;
	}
}

运行结果:

$ ./a.out 
in beginning:	glob=6	var=88
in child,modify the var:glob++,var++
in child:	glob=7	var=89
in parent:	glob=7	var=89

由结果可以看出,父子进程共享数据空间,因此,打印的信息是一致的。

如果将上述代码中的vfork换成fork,其他代码不做修改,重新编译执行后,结果如下:

8$ ./a.out 
in beginning:	glob=6	var=88
in parent:	glob=6	var=88
in child,modify the var:glob++,var++
in child:	glob=7	var=89

由上可知,父子进程打印的信息不一致。即父子进程各自拥有独立的地址空间。

5. 子函数调用vfork创建子进程

首先看运行结果:

$ ./a.out 
1:child pid=7087,ppid=7086
3:child pid=7087,ppid=7086
2:parent pid=7086,ppid=3363
段错误 (核心已转储)

示例代码:

#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>

void test()
{
    pid_t pid;
    pid=vfork();
    if(pid==-1)
    {
       perror("vfork");
       exit(EXIT_FAILURE);
    }
    else if(pid==0)
    {   
       printf("1:child pid=%d,ppid=%d\n",getpid(),getppid());
       return;
    }
    else
       printf("2:parent pid=%d,ppid=%d\n",getpid(),getppid());
}

void fun()
{  
   int i;
   int buf[100];
   for(i=0;i<100;i++)
       buf[i]=0;
   printf("3:child pid=%d,ppid=%d\n",getpid(),getppid());	
}

int main()
{
   pid_t pid;
   test();
   fun(); 
}

出现段错误的原因,见教材197页。

6. fork和vfork的区别

参考链接:

http://blog.csdn.net/buaalei/article/details/5348382

http://blog.sina.com.cn/s/blog_7673d4a5010103x7.html 

原文链接:http://blog.csdn.net/geng823/article/details/40656741

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
本书的目的就是为了讨论这些问题以及其他问题。写作本书的目的源自于读者的这样一种需求,即究竟是什么使得Linux如此独一无二,但本书并不是一本适合Linux初学者的指南,因为这样的书早已在市场上存在了。这些年来,作为一位专业的Linux程序员,我们发现一起工作的很多技术精湛的软件工程师都缺乏或没有Linux编程方面的经验。其中一些工程师一直在寻找与本书类似的图书,但最后总是失望而归。为了让读者不再遭受这样的挫折,本书将帮助读者理解Linux社区的强大意义、已确立的软件开发模型和Linux世界中处理事务的方式。 有许多图书声称是专为Linux编程而写的,其中有许多书确实非常出色,但它们往往过于集中地介绍Linux简单继承自其前辈的内容。在本书中你不会发现这些内容,本书不是一本只介绍Linux和其他老版本UNIX系统共有内容的图书,而是一本介绍现代Linux操作系统的图书。本书不仅仅是另外一本UNIX编程类图书,它试图解释为什么Linux这么成功,并向读者展示在这个主题上被其他图书一笔带过或完全忽略的系统中的某些部分。 在本书中,你将学习到是什么推动了Linux的开发过程。你将了解各种各样常被Linux开发人员使用的工具——编译器、调试器和软件配置管理工具,以及这些工具是如何用来构建应用软件、工具甚至Linux内核自身的。你将学习到Linux系统中使其与其他类UNIX系统真正区分开来的特有组件,你还将深入研究Linux系统的内部工作机理,以便更好地理解作为新一代Linux开发人员你所需要扮演的角色。 你将学习一些新颖的开发方法,包括虚拟化技术的使用和交叉编译的使用(一种为不同的兼容平台编译软件的手段)。你还将学习对于一个没有国界的社区来说软件国际化的重要性——Linux是真正国际性的,它的用户也是如此。最后,你将通过为热门的LAMP(Linux、Apache、MySQL、Perl/Python)组合编写软件来学习Linux在现代因特网上的广泛用途。Linux所包含的内容远不只是Linux内核,作为一位Linux开发人员,意识到这一点是非常重要的。 最重要的是,本书将为未来进一步学习打下基础。通过对推动Linux开发的关键主题的深刻讨论,我们将为你打开通向自由/开放源码软件项目世界的大门。在阅读本书之后,你将能更好地明白你究竟需要了解什么,你并不会在本书中找到所有的答案,但你将具备自己发现这些答案的能力。不论你是使用Linux编写自由软件还是参与一个大型商业软件项目,你都将在阅读本书中有所收获。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值