关于fork()

fork()是linux下常用的系统API,通过系统调用创建一个与原来进程几乎完全相同的进程,也就是两个进程可以做完全相同的事情;也可由于参数的不同,或代码不同分支做完全不相同的事情。

fork调用的一个奇妙之处就是它仅仅被调用一次,却能够返回两次,它可能有三种不同的返回值:
    1)在父进程中,fork返回新创建子进程的进程ID;
    2)在子进程中,fork返回0;
    3)如果出现错误,fork返回一个负值;


由于这个函数的特殊性,所以有很多相关的问题提出来,在此我们汇总一下stackoverflow一些问题。

Question1:

What happens if I call:

if (fork()== fork())

   //do something
 

Answer:

With two forks, you'll end up with four processes: one parent, two children, and one grandchild.

The order that the two forks happen isn't defined since C doesn't require expressions to be evaluated left to right. In the end it won't matter which happens first, so let's pretend the left fork() happens first. When that happens you'll end up with one parent and one child. The parent will get the child's PID back, and the child will get 0.

Let's call the parent A and the child B. Here's what those two processes will look like after the left fork executes:

A          if (<pidof B> == fork())

|

+--B       if (0 == fork())

Now each of them will execute the right fork. Two processes become four. Let's call B's new child C and A's new child D. Again, each fork() call will return one of two values: the new child's PID in the parent process, or 0 in the child process. Here's what our four processes will then become:

A          if (<pidof B> == <pidof D>)

|

+--B       if (0 == <pidof C>)

|  |

|  +--C   if (0 == 0)

|

+--D       if (<pidof B> == 0)

As it happens, process C will be the only one that passes the if check.

 

Question2:

Consider the following piece of code:

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

int main(void)
{
    int i;

    for(i = 0; i < 2; i++)
    {
        fork();
        printf(".");
    }
    return 0;
}

This program outputs 8 dots. How can that be possible?Should not there be 6 dots instead?

Answer

The fork() primitive often stretches the imagination. Until you get a feel for it, you should trace out on paper what each operation is and account for the number of processes.Don't forget that fork() creates a near-perfect copy of the current process.The most significant difference (for most purposes) is that fork()'s return value differs between parent and child. (Since this code ignores the return value, it makes no difference.)

So, at first, there is one process. That creates a second process, both of which print a dot and loop. On their second iteration,each creates another copy, so there are four processes print a dot, and then exit. So we can easily account for six dots, like you expect.

However, what printf() really does is buffer its output. So the first dot from when there were only two processes does not appear when written. Those dots remain in the buffer—which is duplicated at fork(). It is not until the process is about to exit that the buffered dot appears. Four processes printing a buffered dot, plus the new one gives 8 dots.

If you wanted to avoid that behavior, call fflush(stdout); after printf().


Question3:

What would be the output of following fork() calls ?

func(){

   fork();
   fork();
   fork() && fork() || fork();
   fork();

   print("Saikacollection\n");
}

Answer:

Saikacollectionwill be printed 40 times asoutput to the code. This can be explained as follows :-

To understand the output, we need to know following :-

  • On successful execution of a fork() call, new child is created. The process creating the child is called parent process.
  • Fork() call returns pid (process identifier) of the child to parent
  • Fork() returns 0 to the child process.

Convention : All the parents(callers) of the process are written to left and marked with a star.     fork()

  • At the beginning, we have just 1 process, so a fork() call creates a child. Considering the root of the tree as level 1, we can see at level 2 , we have two processes, parent(left) and child(right) .

              fork()

  • fork() again further creates 4 such processes, marked as 1, 2, 3, 4. Since all of the four processes will go through similar code structure further, we can say the total number of processes will be 4 times a single process produces

            fork()&&fork()||fork()

  • Understanding this statement involves, realizing the fact that in C, && operator has more precedence than ||
  • Also, if first of two operands joined by && goes wrong, we don't check the second. Similarly, if first of the two operands of || is true, we don't check the second operand.
  • Consider, the fork() call at 1(marked) node, two processes are created. While the parent gets a positive number(pid) as return, child gets a 0. So, parent executes the second operator, while the child jumps to fork() after || as marked in the figure.
  • The execution of &&fork() for the parent at 4th level, returns a pid for one process, which terminates, while the child of that step, gets a 0. So, it goes for execution of ||fork()
  • the final ||fork() call for child of level 5, further produces a process as a result
  • So, at the end of the step, we have 5 leaves(processes) as marked by underlines in the figure.
  • Had we done the same for all the three nodes, we could have got 5*4 = 20 processes.   fork()
  • Final fork() just doubles the number of process available at that step.
  • So, total number of processes = 2*20 = 40.

 

Ref:

http://stackoverflow.com/questions/11132868/fork-branches-more-than-expected/11133054#11133054

http://blog.csdn.net/jason314/article/details/5640969

http://stackoverflow.com/questions/12881111/output-of-fork-calls/13205210#13205210



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值