Linux IPC之有趣的fork()

在LInux多进程编程中,对于fork(), 相信很多人都不陌生,近来在复习IPC的时候发现了一个好玩的代码,现将其摘录下来,并分析之。

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

int a = 10;

int main(int argc, char *argv[])
{
    int i = 0;
    for(i = 0; i<2; i++)
    {
        pid_t fpid = fork(); // call once return twice.
        if(fpid == 0)
            printf("in child, i=%d pid =%d,ppid=%d,fpid=%d\n",i,getpid(),getppid(),fpid);
        else
            printf("in parent,i=%d pid =%d,ppid=%d,fpid=%d\n",i,getpid(),getppid(),fpid);
    }
    wait();
}
该小代码的输出为:

0 in parent,i=0 pid =6015,ppid=5043,fpid=6016
1 in child, i=0 pid =6016,ppid=6015,fpid=0
2 in parent,i=1 pid =6015,ppid=5043,fpid=6017
3 in child, i=1 pid =6017,ppid=6015,fpid=0
4 in parent,i=1 pid =6016,ppid=6015,fpid=6018
5 in child, i=1 pid =6018,ppid=6016,fpid=0
我们来分析一下这段代码的输出。

首先我们需要复习一下fork 函数的作用与特性。

在Linux系统中, fork用来将当前进程作一次完整的拷贝,并执行,fork函数本身只被调用一次,但却返回两次,在父进程中返回的是新进程的pid,而在新创建出来的子进程中,它返回0,因此我们可以用不同的返回值来实现父进程与子进程不同的行为。

那么于上面那一段代码,它是如何得出如下输入的呢?

bash[5043]
    ---- main[6015]
        ----> fork()---- main*[6016]
	      | #line 0	 |
			 | #line 1		  
                         | ----> fork() ---- main***[6018]
				 | # line 4    |
					       |#line 5 
	----> fork() ---- main**[6017]
	      | #line 2   |
			  | #line 3

在main中,循环两次,i的值分别为0和1, 分别产生main*与main**. 这对应于line 0 和 line2的输出。

在main*中,它的代码与main的代码是一样的,此时 i=0, 只不过它是从fork()之后开始执行,此时fork()的返回值为0, 因此有了line 1的输出。然后在下一次循环的过程中产生main***,并输出line 4.

在main**中,它的代码与main的代码也是一样的,此时 i=1, 那么它在执行完输出之后就退出循环了,它只有一个输出line 3.

在main***中,它的代码与main的代码也是一样的,此时i=1, 那么它在执行完输出之后就退出循还了,它只有一个输出line 5.

输出的顺序其实是不确定的,因为在不同的时刻,哪一个进程优先调度是由内核来管理的,而它的调度行为我们是没办法确定的。

当我们在看一段代码的时候,我们首先要对代码中的关键函数的行为有一个比较深刻的理解,才能够判断出函数的具体行为。我们在学习的时候很容易遇到一些看似简单,实则并不那么容易的问题,它们或许输出的结果与我们的设想大相径庭,这个时候我们要做的就是静下心来好好想想,我们真正理解每个细节吗?

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值