琐记7:关于fork()函数的一些小知识

首先,fork() 函数的主要功能通俗的说是创建一个子进程。这2个进程是相互独立的两个进制,它们共享的内容只有代码段。这时候就要提到我们之前学到 的一个知识点——内存四区了,在栈,堆,数据段和代码段这四个大块中,它们父子俩的前三个是完全区分开的,像这样一个函数:

int main()
{
	int count = 0;
	pid_t pid = fork();

	count++;
	printf ("count = %d\n", count);
	
	return 0;
}

它的答案就是两个1,而不是1和2 。

另外就是父子进程的运行先后问题,它们的执行先后是不确定的(虽然笔者在red hat实验了很多次,都是子进程先执行)。

关于这个函数的返回值问题,因为它有2个进程,自然而然的它有也2个返回值,在父进程中,返回值为子进程的ID,在子进程中,返回值为0;我们可以使用getpid()函数来获取它们各自的ID号,如下:

int main()
{
	pid_t pid = fork();
	if (pid == -1)
	{
		perror ("fork");
		return -1;
	}
	
	if (pid > 0)         // 父进程
	{
		printf ("我是父进程,pid = %d\n", getpid());
	}
	else if (pid == 0)   // 子进程
	{
		printf ("我是子进程,pid = %d\n", getpid());
	}

	return 0;
}

因为每调用一次fork() 函数就会产生一个相应的子进程,所以,很显然的,连续调用三次fork() 就能产生总共8个进程,这不难理解。但,不要觉得这很容易理解,我们来看一下下面这道题,判断一下会有 多少个a被打印出来:


int main()
{
	fork();
	fork() && fork() || fork();
	fork();
	
	printf("a\n");
	
	return 0;
}

首先,我们很容易理解的是,第3行和第5行代码,就是进程的翻倍,主要就是看第四行代码的意思,我们假设主进程为1,在第三行代码执行结束时,它产生了子进程2,我们分开讨论,判断了1的执行结果翻倍就是总的进程数。

在第四行代码中:2进程在执行完第一个fork() 函数后产生了它的子进程3,2进程的返回值为3进程的ID(一个大于0的正整数),所以就执行&&操作的后半部分第二个fork() 函数,产生子进程4,返回值为4的ID,所以就不执行 || 后面的操作了,到此,2进程结束; 再回来看它的子进程3,它作为子进程,返回值为0,所以&&的后半部分是执行不了了,但&&完之后的结果就是0,可以进行接下来的 || 操作,于是它又产生了一个子进程5;同样,2进程产生的另一个 子进程4和3进程是一个道理,也要执行||操作的后半部分,产生一个子进程6。

到此,第四行代码全部执行完毕,产生了包括2在内总共5个进程,于是最终的结果就是2*5*2 = 20个进程。


另外,与fork() 函数相类似的还有一个vfork() 函数, 它有这样一些特点:

1) vfork() 函数的子进程必须显式调用;

2)vfork() 函数的父子进程共享数据段;

3)vfork() 函数的子进程要先于父进程执行,即子进程运行结束,CPU才能调度到父进程。


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值