vfork()函数和fork()函数实现子进程的异同

      除了fork()函数,还可以用vfork()函数来创建子进程。

      (1)使用fork()创建一个子进程时,子进程只是完全复制父进程的资源。子进程独立于父进程,具有良好的并发性。而vfork()创建的子进程,操作系统并不将父进程的地址空间完全复制到子进程,用vfork()创建的子进程共享父进程的地址空间,也就是说,子进程完全运行在父进程的地址空间上。子进程对该地址空间中任何数据的修改同样为父进程所见。

      (2)使用fork()创建子进程时,哪个进程先运行取决于系统的调度算法。而vfork()保证子进程先运行,当子进程调用exec或exit之后,父进程才可能被调度运行。如果在调用exec或exit之前子进程要依赖父进程的某个行为,就会导致死锁。

      (3)fork()创建子进程时,子进程要将父进程几乎每种资源都复制,所以fork()是一个开销很大的系统调用。假设fork一个子进程后,立即调用exec执行另外一个应用程序,那么fork过程中子进程对父进程地址空间的复制将是一个多余的过程。vfork()不会拷贝父进程的地址空间,这大大减小了系统开销。

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>

int globVar = 0;

int main(void)
{
	pid_t  pid;
	int    var = 0, i;
	
	printf("fork is diffirent with vfrok \n");

	pid = fork();
	//pid = vfork();
	switch(pid) {
		case 0:
			i = 3;
			while(i-- > 0)
			{
				printf("Child process is running\n");
				globVar++;
				var++;
				sleep(1);
			}
			printf("Child's globVar = %d,var = %d\n",globVar,var);
			break;
		case -1:
			perror("Process creation failed\n");
			exit(0);
		default:
			i = 5;
			while(i-- > 0)
			{
				printf("Parent process is running\n");
				globVar++;
				var++;		
				sleep(1);
			}
			printf("Parent's globVar = %d ,var = %d\n", globVar ,var);
			exit(0);
	}
}
      使用fork()创建子进程时,运行结果如下:

      使用fork()创建子进程时,子进程继承了父进程的全局变量和局部变量。子进程中,最后全局变量globVar和局部变量var的值均递增3,分别为3和3,而父进程中两者分别递增5,分别都是5。这证明了子进程有自己独立的地址空间。

  

    注释掉fork()的代码,使用vfork()创建子进程,运行结果如下:




      vfork()创建子进程后,父进程中globVar和var最后均递增了8(但var最后运行结果是2277504,这个还比较费解,暂时还没搞清楚什么原因导致了这个数字出现错乱?).这是因为vfork()的子进程共享父进程的地址空间,子进程修改变量对父进程是可见的。


      fork()创建子进程后,父子进程的执行顺序是不确定的。而vfork(),子进程在父进程之前执行。


注意:使用vfork()时要谨慎,最好不要允许子进程修改与父进程共享的全局变量和局部变量。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值