The fork () function in Linux is detailed (original!!) Example)

Source: Internet
Author: User

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

The fork () call will copy a new process that is almost identical to the current process (except for the fork's return value), each of which has its own space, each with its own local variables, and the values of the local variables of the two processes have equal values at the fork point, and only the values returned by the fork are different. In this example, the value of the local variable PID is different, the PID variable of the new process is 0, the original process PID is the process ID value of the new process. This way, two parallel processes run before the results you see will appear.

First, Fork Introduction knowledge

A process, including code, data, and resources assigned to the process. The fork () function creates a process that is almost identical to the original process through a system call, that is, two processes can do exactly the same thing, but two processes can do different things if the initial parameters or the variables passed in are different.
After a process calls the fork () function, the system first 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 new process, with only a few values that are different from the value of the original process. The equivalent of cloning a self.

Let's look at an example:

[CPP]View Plaincopy
  1. /*
  2. * FORK_TEST.C
  3. * Version 1
  4. * Created on:2010-5-29
  5. * Author:wangth
  6. */
  7. #include <unistd.h>
  8. #include <stdio.h>
  9. int main ()
  10. {
  11. pid_t Fpid; Fpid represents the value returned by the fork function
  12. int count=0;
  13. Fpid=fork ();
  14. if (Fpid < 0)
  15. printf ("Error in fork!");
  16. else if (Fpid = = 0) {
  17. printf ("I am the child process, my process ID is%d/n", getpid ());
  18. printf ("I am father's son/n");//For some people, Chinese looks more straightforward.
  19. count++;
  20. }
  21. else {
  22. printf ("I am the parent process, my process ID is%d/n", getpid ());
  23. printf ("I am the child his father/n");
  24. count++;
  25. }
  26. printf ("Statistic Result:%d/n", count);
  27. return 0;
  28. }

The operating result is:
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 the kid, his father.
The statistic results are: 1
Before the statement fpid=fork (), only one process executes the code, but after this statement, it becomes two processes executing, the two processes are almost identical, and the next statement to be executed is the IF (fpid<0) ...
Why the fpid of two processes is different, which is related to the characteristics of the fork function. A wonderful thing about a fork call is that it is called only 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 sub-process, fork returns 0;
3) If an error occurs, fork returns a negative value;

After the fork function finishes executing, if the new process is created successfully, there are two processes, one child process and one 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 child process or a parent process by the value returned by the fork.

Quote a netizen to explain why the value of Fpid is different in the parent-child process. "In fact, the equivalent of a linked list, the process forms a linked list, the parent process fpid (p means point) to the process ID of the child process, because the child process has no child process, so its fpid is 0.
There are two possible reasons for fork errors:
1) The current number of processes has reached the system-specified limit, when the value of errno is set to Eagain.
2) system memory is low, then the value of errno is set to Enomem.
After a successful creation of a new process, there are two fundamentally identical processes in the system, which do not have a fixed sequencing and which process first executes the process scheduling policy to look at the system.
Each process has a unique (distinct) process ID, which can be obtained through the getpid () function, a variable that records the PID of the parent process, and the value of the variable can be obtained through the getppid () function.
After the fork executes, two processes appear,

Some people say that the content of the two process is exactly the same Ah, how to print the result is not the same ah, that is because the reason for judging the conditions, the above list is only the process of code and instructions, and variables ah.
After the fork is executed, the variable for process 1 is count=0,fpid! =0 (parent process). The variable for process 2 is count=0,fpid=0 (child process), the variables of both processes are independent, there are different addresses, not shared, and this should be noted. We can say that we are using fpid to identify and manipulate parent-child processes.
Others may wonder why the code is not copied from # include, because Fork is a copy of the current situation of the process, and when the fork is executed, the process has finished executing int count=0;fork only the next code to execute to the new process.

Second, fork advanced knowledge

Let's look at a piece of code:

[CPP]View Plaincopy
  1. /*
  2. * FORK_TEST.C
  3. * Version 2
  4. * Created on:2010-5-29
  5. * Author:wangth
  6. */
  7. #include <unistd.h>
  8. #include <stdio.h>
  9. int main (void)
  10. {
  11. int i=0;
  12. printf ("I son/pa ppid pid fpid/n");
  13. Ppid refers to the parent process PID of the current process
  14. PID refers to the PID of the current process,
  15. Fpid refers to the value that the fork returns to the current process
  16. for (i=0;i<2;i++) {
  17. pid_t fpid=fork ();
  18. if (fpid==0)
  19. printf ("%d child%4d%4d%4d/n", I,getppid (), Getpid (), fpid);
  20. Else
  21. printf ("%d parent%4d%4d%4d/n", I,getppid (), Getpid (), fpid);
  22. }
  23. return 0;
  24. }

The operating result is:
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 interesting, let's analyze it carefully:
First step: In the parent process, the instruction executes into the For loop, i=0, and then after execution Fork,fork executes, there are two processes in the system, namely p3224 and p3225 (which I use pxxxx to represent the process ID of xxxx). You can see that the parent process p3224 is p2043, and the parent process p3225 the child process is exactly p3224. We use a linked list to represent this relationship:
p2043->p3224->p3225
After the first fork, the variable for the p3224 (parent process) is i=0,fpid=3225 (the fork function returns to the child process ID in the parent process), with the following code:

[C-sharp]View Plaincopy
    1. for (i=0;i<2;i++) {
    2. pid_t fpid=fork ();//execution complete, i=0,fpid=3225
    3. if (fpid==0)
    4. printf ("%d child%4d%4d%4d/n", I,getppid (), Getpid (), fpid);
    5. Else
    6. printf ("%d parent%4d%4d%4d/n", I,getppid (), Getpid (), fpid);
    7. }
    8. return 0;

The variable for the p3225 (child process) is i=0,fpid=0 (the fork function returns 0 in the subprocess), and the Code content is:

[C-sharp]View Plaincopy
    1. for (i=0;i<2;i++) {
    2. pid_t fpid=fork ();//execution complete, i=0,fpid=0
    3. if (fpid==0)
    4. printf ("%d child%4d%4d%4d/n", I,getppid (), Getpid (), fpid);
    5. Else
    6. printf ("%d parent%4d%4d%4d/n", I,getppid (), Getpid (), fpid);
    7. }
    8. return 0;

So print out the results:
0 Parent 2043 3224 3225
0 Child 3224 3225 0
The second step: assume that the parent process p3224 first, when entering the next loop, I=1, then fork, the system added a process p3226, for the parent process at this time, p2043->p3224 (the current process)->p3226 (the child process was created).
For child process p3225, after the first loop is executed, i=1, then fork, a new process p3227 is added to the system, p3224->p3225 (the current process)->p3227 (the child process being created). From the output you can see that p3225 was originally a p3224 child process and now becomes the parent process of p3227. Father and son are relative, this people should be easy to understand. As long as the current process has been fork, the process becomes the parent process, which prints out the parent.
So print out the result:
1 Parent 2043 3224 3226
1 Parent 3224 3225 3227
Step three: The second step creates two process p3226,p3227, which ends when the printf function finishes executing, because the two processes cannot enter the third loop, cannot fork, and executes return 0;
Here are the results printed by p3226,p3227:
1 Child 1 3227 0
1 Child 1 3226 0
The attentive reader may notice that p3226,p3227 's parent process should not be p3224 and p3225, how could it be 1? Here we have to talk about the process of creating and dying, and after p3224 and p3225 are done with the second loop, the main function should quit, that is, the process is dead, because it has done everything. p3224 and p3225 death, p3226,p3227 There is no parent process, which is not allowed in the operating system, so p3226,p3227 parent process is set to P1, P1 is never dead, as for why, here first not introduced, stay to "three, fork advanced knowledge" Speak.
To summarize, this program executes the following process:

This program eventually produces 3 sub-processes and executes the printf () function 6 times.
Let's look at one more code:

[CPP]View Plaincopy
  1. /*
  2. * FORK_TEST.C
  3. * Version 3
  4. * Created on:2010-5-29
  5. * Author:wangth
  6. */
  7. #include <unistd.h>
  8. #include <stdio.h>
  9. int main (void)
  10. {
  11. int i=0;
  12. for (i=0;i<3;i++) {
  13. pid_t fpid=fork ();
  14. if (fpid==0)
  15. printf ("son/n");
  16. Else
  17. printf ("father/n");
  18. }
  19. return 0;
  20. }

The result of its execution is:
Father
Son
Father
Father
Father
Father
Son
Son
Father
Son
Son
Son
Father
Son
This is not a detailed explanation, just a rough analysis.
For I=0 1 2
Father Father father
Son
Son father
Son
Son father father
Son
Son father
Son
Each of these lines represents the run print result of a process, respectively.
Summing up the rules, for this n-cycle situation, the number of times to execute the printf function is 1+2+4+......+2n-1, and the number of child processes created is 1+2+4+......+2n-1.(Thanks to Gao_jiawei Netizens pointed out the mistake, originally I concluded that "the number of times to execute the printf function is 1+2+4+......+2n), the number of child processes created is 1+2+4+......+2n", which is wrong)
Some people on the internet say that n cycles produce a 1+2+4+......+2n process, which is wrong, I hope you need to pay attention.

See http://202.117.3.13/wordpress/?p=81 (the Last of the blog post) for mathematical reasoning.
At the same time, if you want to test a program in the end to create a few sub-processes, the best way is to call the printf function to print the PID of the process, that is, call printf ("%d/n", Getpid ()), or through printf ("+/n"), to determine the production of several processes. Some people want to count the creation of several processes by invoking printf ("+"), which is not appropriate. I'll analyze it for specific reasons.
The usual, let's look at the following code:

[CPP]View Plaincopy
  1. /*
  2. * FORK_TEST.C
  3. * Version 4
  4. * Created on:2010-5-29
  5. * Author:wangth
  6. */
  7. #include <unistd.h>
  8. #include <stdio.h>
  9. int main () {
  10. Pid_t Fpid;//fpid represents the value returned by the fork function
  11. printf ("fork!");
  12. printf ("fork!/n");
  13. Fpid = fork ();
  14. if (Fpid < 0)
  15. printf ("Error in fork!");
  16. else if (Fpid = = 0)
  17. printf ("I am the child process, my process ID is%d/n", getpid ());
  18. Else
  19. printf ("I am the parent process, my process ID is%d/n", getpid ());
  20. return 0;
  21. }

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 you put the statement printf ("fork!/n"); Comment out, execute printf ("fork!");
The result of the new program execution is:
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 is related to the buffer mechanism of printf, when some content of printf, the operating system just put the content in the stdout buffer queue, and did not actually write to the screen. However, as soon as you see that there is/N, the stdout is refreshed immediately, so you can print immediately.
printf ("fork!") was run After, "fork!"  Just put in the buffer, the program runs to the fork buffer inside the "fork!" Quilt process copy passed. Therefore, in the sub-degree of stdout buffer inside there is also fork!.  So, what you finally see is fork!. was printf 2 times!!!
While running printf ("fork! /n ")," fork! " is immediately printed on the screen, and then the stdout buffer in the sub-process to fork will not have fork! Content. So the results you see will be fork!. was printf 1 times!!!
So printf ("+") does not respond correctly to the number of processes.
It may be a bit tiring for everyone to see so much, but I have to stick to the last piece of code to further analyze the fork function.

[CPP]View Plaincopy
    1. #include <stdio.h>
    2. #include <unistd.h>
    3. int main (int argc, char* argv[])
    4. {
    5. Fork ();
    6. Fork () && fork () | | Fork ();
    7. Fork ();
    8. return 0;
    9. }

The problem is not the main process itself, how many processes the program has created.
In order to answer this question, we first do the cheat, first with a program to verify how many processes.

[C-sharp]View Plaincopy
    1. #include <stdio.h>
    2. int main (int argc, char* argv[])
    3. {
    4. Fork ();
    5. Fork () && fork () | | Fork ();
    6. Fork ();
    7. printf ("+/n");
    8. }

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 still 19 of processes.
The first fork and the last fork are sure to be executed.
Mainly in the middle of the 3 fork, you can draw a diagram to describe.
Here you need to be aware of && | | Operator.
A&&b, if the a=0, there is no need to continue to implement &&B, a non-0, you need to continue to implement &&b.
a| | B, if A is not 0, there is no need to continue execution | | B, a=0, we need to continue to execute. | | B.
Fork () is different from the return values of the parent and child processes, according to A&&b and a| | B's branch to draw, you can draw 5 branches.

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

Third, fork advanced knowledge

This piece I mainly on the fork function to tell the operating system process creation, death and scheduling. Because of time and energy constraints, I wrote here first, next time I try to get the rest of the content.

The fork () function in Linux is detailed (original!!) Example)

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.