An example analysis of fork () function in Linux _linux

Source: Internet
Author: User

First, fork introductory knowledge

A process that includes code, data, and resources assigned to the process. The fork () function creates a process that is almost exactly the same as the original process through system calls, where two processes can do exactly the same thing, but two processes can do different things if the initial parameters or incoming variables are different.

Once a process calls the fork () function, the system assigns resources to the new process, such as space for storing data and code. All the values of the original process are then copied to the new process, with only a few values different from the values of the original process. The equivalent of cloning a self.

Let's take a look at an example:

 * 
 * fork_test.c 
 * Version 1 * 
 Created on:2010-5-29 
 * author:wangth 
 / 
#include <unistd.h& gt; 
#include <stdio.h> 
int main () 
{ 
 pid_t fpid;//fpid represents the value 
 int count=0 
 returned by the fork function; Fpid=fork (); 
 if (Fpid < 0) 
 printf ("Error in fork!"); 
 else if (fpid = 0) { 
 printf ("I am the child process, my process ID is%d/n", getpid ()); 
 printf ("I'm Dad's son/n");//For some people, Chinese looks more straightforward. 
 count++; 
 } 
 else { 
 printf ("I am the parent process, my process ID is%d/n", getpid ()); 
 printf ("I am the child his father/n"); 
 count++; 
 } 
 printf ("Statistic Result:%d/n", count); 
 return 0; 
} 

The results of the operation are:

I am the child process and my process ID is 5574
I'm the father's son.
The statistic results are: 1
I am the parent process, my process ID is 5573
I'm a child, his father.
The statistic results are: 1

Before the statement fpid=fork (), only one process executes the code, but after that statement, it becomes two processes executing, almost exactly the same, and the next statement to be executed is if (fpid<0) ...

Why is the fpid of the two processes different, which is related to the characteristics of the fork function. One of the wonders of fork invocation is that it is only invoked once, but it can return two times, and it may have three different return values:

1 in the parent process, fork returns the process ID of the newly created child process;
2) in the subprocess, the fork returns 0;
3 If an error occurs, fork returns a negative value;

After the fork function completes, if the creation of a new process succeeds, there are two processes, one is a child process, the other is the parent process. In the subprocess, the fork function returns 0, and in the parent process, fork returns the process ID of the newly created child process. We can determine whether the current process is a subprocess or a parent process by fork the returned value.

Quote a netizen to explain why the value of Fpid is different in a parent-child process. "In fact, the equivalent of a linked list, the process formed a linked list, the parent process fpid (p means point) to the process ID of the child process, because the child process does not have a subprocess, so its fpid is 0."

There are two possible reasons for fork error :

1 The current number of processes has reached the upper limit of the system, when the errno value is set to Eagain.
2 The system is low on memory, when the value of errno is set to Enomem.

After the successful creation of the new process, there are two fundamentally identical processes in the system, which do not have a fixed sequence, and which process executes the process scheduling strategy to see the system first

Each process has a unique (and distinct) process identifier, which can be obtained through the getpid () function, a variable that records the PID of the parent process, and can be obtained by the getppid () function.

After the fork execution, there are two processes,

Some people say two process content exactly the same Ah, how to print the results are different ah, that is because the reason for judging conditions, the above list is only the process of code and instructions, and variables Ah

After the fork is executed, the process 1 variable is count=0,fpid! =0 (parent process). The variables of Process 2 are count=0,fpid=0 (subprocess), the variables of these two processes are independent, exist in different addresses, not shared, this should be noted. It can be said that we are through the fpid to identify and manipulate the parent-child process.

Others may wonder why the code is not copied from #include, because Fork is copying the current situation of the process, executing fork, the process has already performed int count=0;fork copies only the next code to be executed to the new process.

second, fork advanced knowledge

First look at a code:

 * 
 * fork_test.c 
 * Version 2 * 
 Created on:2010-5-29 
 * author:wangth 
 / 
#include <unistd.h& gt; 
#include <stdio.h> 
int main (void) 
{ 
 int i=0; 
 printf ("I son/pa ppid pid fpid/n"); 
 Ppid refers to the current process's parent process PID 
 //pid refers to the current process's PID, 
 //fpid refers to fork return to the current process's value for 
 (i=0;i<2;i++) { 
 pid_t fpid= Fork (); 
 if (fpid==0) 
  printf ("%d child%4d%4d%4d/n", I,getppid (), Getpid (), fpid); 
 else 
  printf ("%d parent%4d%4d%4d/n", I,getppid (), Getpid (), fpid); 
 return 0; 
} 

The results of the operation are:

I son/pa ppid pid fpid
0 Parent 2043 3224 3225
0 Child 3224 3225 0
1 Parent 2043 3224 3226
1 Parent 3224 3225 3227
1 Child 1 3227 0
1 Child 1 3226 0

This code is more interesting, we have to seriously analyze:

Step One: in the parent process, the instruction executes in the For loop, i=0, and then executes fork,fork execution, and there are two processes in the system, p3224 and p3225 (later I use pxxxx to represent processes with a process ID of xxxx). You can see that the parent process p3224 the parent process is p2043, and the child process p3225 the parent process is exactly p3224. We use a linked list to represent this relationship:

p2043->p3224->p3225

After the first fork, the p3224 (parent process) variable is i=0,fpid=3225 (the fork function returns the child process ID in the parent process), and the code reads:

 for (i=0;i<2;i++) { 
 pid_t fpid=fork ()//execution completed, i=0,fpid=3225 
 if (fpid==0) 
 printf ("%d child%4d%4d,%4d/n" , I,getppid (), Getpid (), fpid); 
 else 
 printf ("%d parent%4d%4d%4d/n", I,getppid (), Getpid (), fpid); 
return 0; 

The variable for the p3225 (subprocess) is i=0,fpid=0 (the fork function returns 0 in the subprocess), and the code reads:

 for (i=0;i<2;i++) { 
 pid_t fpid=fork ()//execution completed, i=0,fpid=0 
 if (fpid==0) 
 printf ("%d child%4d%4d,%4d/n" , I,getppid (), Getpid (), fpid); 
 else 
 printf ("%d parent%4d%4d%4d/n", I,getppid (), Getpid (), fpid); 
return 0; 

So print out the result:

0 Parent 2043 3224 3225
0 child 3224 3225 0

Step Two: assume that the parent process p3224 first, and when it goes to the next loop, I=1, then executes fork, and a new process p3226 is added to the system, p2043->p3224 (current process) for the parent process at this time-> p3226 (the child process being created).

For Subprocess p3225, after the first loop, I=1, and then execute fork, a new process p3227 in the system, p3224->p3225 (the current process)->p3227 (the child process being created) for this process. From the output you can see that p3225 was originally a p3224 subprocess and now becomes the p3227 parent process. Father and son are relative, this should be easy to understand. As soon as the current process executes the fork, the process becomes the parent process, and it prints out the parent.

So print out the result is:

1 Parent 2043 3224 3226
1 parent 3224 3225 3227

Step Three: The second step creates two process p3226,p3227, which ends after the printf function finishes, because the two processes cannot go into the third loop, cannot be fork, the execution return 0, and so are other processes.

The following are the results printed by p3226,p3227:

1 Child 1 3227 0
1 Child 1 3226 0

Attentive readers may notice that p3226,p3227 's parent process shouldn't be p3224 and p3225, how could it be 1? Here's the process of creating and dying, and after p3224 and p3225 are done with the second loop, the main function quits, and the process dies because it's done everything. After the death of p3224 and p3225, p3226,p3227 No father process, this is not allowed in the operating system, so the p3226,p3227 of the parent process is set to P1, P1 is never dead, as for why, here is not introduced, stay to "three, fork higher knowledge" Speak.

To sum up, the process of executing this program is as follows:

This program eventually produced 3 subprocess, and executed the printf () function 6 times.

Let's take a second look at the code:

 * 
 * fork_test.c 
 * Version 3 * 
 Created on:2010-5-29 
 * author:wangth 
 / 
#include <unistd.h& gt; 
#include <stdio.h> 
int main (void) 
{ 
 int i=0; 
 for (i=0;i<3;i++) { 
 pid_t fpid=fork (); 
 if (fpid==0) 
  printf ("son/n"); 
 else 
  printf ("father/n"); 
 } 
 return 0; 

} 

The results of its implementation are:

Father
Son
Father
Father
Father
Father
Son
Son
Father
Son
Son
Son
Father
Son

There's no detailed explanation, just a ballpark analysis.

Each row represents the running print result of a process.

Summing up the law, for this n-cycle situation, the number of Execute printf function is 2* (1+2+4+......+2n-1) times, the number of child processes created is 1+2+4+......+2n-1. (Thanks to the Gao_jiawei Netizen pointed out the mistake, originally my conclusion is "the number of 2* (1+2+4+......+2n) times, the number of child processes created 1+2+4+......+2n", which is wrong)

Someone on the net said N cycles produce 2* (1+2+4+......+2N) process, this is wrong, I hope you need to pay attention.

At the same time, if you want to test a program in the end to create a few child processes, the best way is to call the printf function print the process of the PID, also called printf ("%d/n", Getpid ()), or through printf ("+/n"), to determine the number of processes generated. It is not appropriate for someone to count the creation of several processes by calling printf ("+"). I will analyze the specific reasons.

As usual, let's take a look at the following code:

 * 
 * fork_test.c 
 * Version 4 * 
 Created on:2010-5-29 
 * author:wangth 
 / 
#include <unistd.h& gt; 
#include <stdio.h> 
int main () { 
 pid_t fpid;//fpid represents the value returned by the fork function 
 //printf ("fork!"); 
 printf ("fork!/n"); 
 Fpid = fork (); 
 if (Fpid < 0) 
 printf ("Error in fork!"); 
 else if (fpid = 0) 
 printf ("I am the child process, my process ID is%d/n", getpid ()); 
 else 
 printf ("I am the parent process, my process ID is%d/n", getpid ()); 
 return 0; 
} 

The results of the implementation are as follows:

fork!
I am The parent process, my process ID is 3361
I am the child process and my process ID is 3362

If the statement printf ("fork!/n"), comment out, execute printf ("fork!");
The results of the new program are:

fork! I am The parent process, my process ID is 3298
fork! I am the child process and my process ID is 3299

The only difference between the program is a/n carriage return symbol, why the result is so big difference?

This has to do with the buffering mechanism of printf, when printf some content, the operating system simply put the content in the stdout buffer queue, and did not actually write to the screen. However, whenever you see A/N, the stdout is immediately refreshed, so you can print it right away.

Run printf ("fork!") After the "fork!"  is only put into the buffer, the program runs to the fork buffer inside the "fork!" The quilt process has been copied past. Therefore, the stdout buffer inside the sub-level also has a fork!.  So, what you end up seeing is fork!. It's been printf 2 times,!!!!.

and run printf ("fork! /n ")," fork! " is immediately printed on the screen, and then fork in the stdout buffer in the subprocess will not have fork! Content. So the result you see will be fork!. It's been printf 1 times,!!!!.

So printf ("+") is not able to respond correctly to the number of processes.

It may be a bit tiring for everyone to see so much, but I have to put up the last code to further analyze the fork function.

#include <stdio.h> 
#include <unistd.h> 
int main (int argc, char* argv[]) 
{ 
 fork (); 
 Fork () && fork () | | Fork (); 
 Fork (); 
 return 0; 
} 

The problem is not the main process itself, how many processes the program has created.
In order to solve this problem, we first do the harm, first use the program to verify how many processes there.

 #include <stdio.h> 
int main (int argc, char* argv[]) 
{ 
 fork (); 
 Fork () && fork () | | Fork (); 
 Fork (); 
 printf ("+/n"); 
} 

The answer is a total of 20 processes, minus the main process, and 19 more processes.

Let's take a closer look at why there are 19 more processes.
The first fork and the last fork will certainly be carried out.
Mainly in the middle of 3 fork, you can draw a picture to describe.
Here you need to pay attention to && and | | Operator.
A&&b, if a=0, there is no need to continue to carry out &&b, A is not 0, you need to continue to perform &&b.
a| | B, if A is not 0, there is no need to continue to execute | | B, a=0, you need to continue the implementation of | | B.

Fork () is different for the return values of the parent and child processes, according to the a&&b and a| above | B's branch for drawing, can draw 5 branches.

Plus the front fork and the last fork, a total of 4*5=20 processes, minus the main main process, is 19 processes.

Iii. Fork Higher-order knowledge

This one I mainly on the fork function to talk about the creation, death and scheduling of operating system processes. Because of time and energy limit, I write here first, next time I try to get the rest of the content.

The above is the entire content of this article, I hope to help you learn, but also hope that we support the cloud habitat community.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.