Simple introduction-the fork () function of UNIX multi-process Programming

Source: Internet
Author: User
Tags glob

0 Preface

Last week, I was reading the eighth chapter of advanced programming in the Unix environment-process control. In this chapter, I understand the principles of some processes in UNIX. Next I will mainly explain the three most important functions in the process. Let everyone thoroughly understand the process by reading this article. Hope to help you.

1. process environment

Before learning a process, you must understand the Unix process environment. How the system terminates the process, starts and terminates a program, and runs the program. This helps you understand the running principle of the process. These contents are all in my previous article. Please note: http://blog.csdn.net/wallwind/article/details/6968323. The article is more detailed.

2. Process concept:

A process mainly contains three elements:

A) an executable program;

B) all data associated with the process (including variables, memory space, buffers, etc );

C) Execution context of the program ).

Simply put, a process represents a State in one execution process of an executable program. The management of processes by the operating system is typically completed through the process table. Each table entry in the table records a process in the current operating system. For a single CPU, only one process occupies the CPU at each specific time, but there may be multiple active (waiting for execution or continuing execution) processes in the system at the same time.

3 fork () function

The fork () function is the core function of the process. When fork is called, The system creates a new process and becomes a child process ). The fork function is defined as follows:

# Include <unistd. h> pid_t fork (void); // return value: the child process returns 0, the parent process returns the child process ID, and the error returns-1

From the returned value, we can see that the fork function is called once, but returns twice. The difference is that the return value is 0 in the child process, and the return value of the parent process is the ID of the new Child process.

The above concepts may be vague for beginners. How can we understand fork?

When you see the fork, you can understand the fork as a "fork". At the same time as the fork, the generated sub-process copies basically everything in the parent process, including code, data, and resources allocated to processes. That is, the child process is almost the same as the parent process. However, sub-processes may call other functions according to different situations. For example, the exec function.

Let's take a look at the following typical and simple examples.

# Include "apue. H "int glob = 6; char Buf [] =" A write to stdout \ n "; int main (void) {int Var = 88; pid_t PID; if (write (stdout_fileno, Buf, sizeof (BUF)-1 )! = Sizeof (BUF)-1) printf ("writeerror"); printf ("before fork with linefeed \ n"); printf ("before fork without linefeed "); // printf ("\ n"); If (pid = fork () <0) {printf ("fork error");} else if (pid = 0) {printf ("I am child process, pid = % d \ n", getpid (); printf ("My parentprocess's pid = % d \ n ", getppid (); glob ++; var ++;} else {printf ("this is parentprocess, pid = % d \ n", getpid ()); // var ++;} printf ("pid = % d, glob = % d, Var = % d \ n", getpid (), glob, VAR ); exit (0 );}

Output result:

I hope the new user can repeat the above Code and run it again.

We analyze the above results step by step. First, we can see that the two lines of text are output only once.

"A write to stdout"

"Befork forkwhit h line break ".

That is, only one process executes these two output statements. For the time being, we will not analyze those without line breaks.

When the program calls fork, a process occurs in the program, that is, two processes are being executed.

See the simple graph below

As mentioned above, the fork function will return different function values for different calls:

1) in the parent process, fork returns the process ID of the newly created sub-process;

2) in the sub-process, fork returns 0;

3) if an error occurs, fork returns a negative value;

Now let's look at several functions in the program. The Write function writes Buf content to the standard stream. It is used for output only.

We are concerned with the getpid () and getppid () functions.

The getpid () function is used to output the ID of the current process. getppid () is used to obtain the ID of the parent process of the current process. You can see from the output result comparison, the parent ID obtained by the child process is the same as that obtained by the parent process.

Let's take a look at the global variable glob, which is a variable outside the function. The child process processes glob ++. At this time, 7 is output. The parent process does not process 6 directly. We can know that the two glob variables are displayed in two copies. Irrelevant.

The same result is returned for the local variable VAR ....

Now let's explain why

Printf ("before fork with linefeed \ n"); printf ("before fork without linefeed ");

The previous sentence is output only once, and the following sentence is output twice.

We can find that printf ("before fork with linefeed \ n"); this sentence contains the meaning of "\ n. While

Printf ("before fork without line break ");

Yes.

We need to know that the printf function has a buffer mechanism, similar to the write function we use, but when we output what we want, the system only places the content in the Buffer Queue of stdout standard output. When "\ n" is encountered, the system clears the buffer and outputs it to the screen.

Printf ("beforefork with linefeed \ n ");

After execution, there is no data in the buffer, and no content can be output when the child process executes again. However, when printf ("before fork without line break");, the child process will output the stdout content again. That is, the source of the content is on both sides. If you change the book order, the results will be different.

3 fork difficulty (advanced tutorial)

Csdn saw an article about fork. In-depth explanation. Next I will present my debugging and understanding to you. First, let's look at a piece of code:

#include "apue.h" int main(void){       int i=0;       pid_t pid;        for(i=0;i<2;i++)       {                if((pid=fork())<0){                        printf("forkerror\n");                }else if(pid==0){                       printf("%d,childself's pid=%d,parent's pid=%d,returnid=%d\n",i,getpid(),getppid(),pid);               }else{                       printf("%d,parentself's pid=%d,parent's father's pid=%d,returnid=%d\n",i,getpid(),getppid(),pid);                        sleep(2);//inorder tochild output first                }       }       exit(0);}

The output result is:

Analyze our results. The output starting with 0 is two rows, and the output starting with 1 is four rows.

Then we start to observe the PID results. From the PID results, we can find a relationship.

Both 9278-30361-30362-30363-

9278-30361-30364

You must know that the fork function returns 0 when the sub-process calls the function, and the parent process returns the ID of the sub-process when calling the function.

Step 1:

if((pid=fork())<0){                        printf("forkerror\n");                }else if(pid==0){                       printf("%d,childself's pid=%d,parent's pid=%d,returnid=%d\n",i,getpid(),getppid(),pid);                }else{                       printf("%d,parentself's pid=%d,parent's father's pid=%d,returnid=%d\n",i,getpid(),getppid(),pid);                        sleep(2);//inorder tochild output first                }

The output result is:

This is the first loop output.

Both childpid and return are the 30361 generated by the parent ID 30361.

Now there are two processes.

The process IDs are 30362 and 30361, respectively.

The second loop output.

We know that the two processes are 30362 and 30361. The two processes run their own Code respectively.

Ü at this time, a process with a PID of 30362 is executed:

Loop. The result is as follows:



A sub-process 30363 is generated.

Ü the 30361 process executes its own code again, which is part of the above loop.

A sub-process 30364 is generated.

From the program and output results, we can see that our program has 6 copies.

In this example, fork generates three sub-processes and outputs six times. You can understand the working principle of fork.

Another example:

This is a typical example of a loop:

#include <unistd.h>#include<stdio.h> int main(void){       pid_t pid;       int i=0;       int c_cout=0;       int p_cout=0;       for(i=0;i<5;i++)       {                if((pid=fork())<0){                        printf("forkerror\n");                }else if(pid==0){                        c_cout++;               }else{                        p_cout++;                }        }       printf("c_cout=%d,p_cout=%d,pid=%d\n",c_cout,p_cout,getpid()); }

Output result: c_cout = 5, p_cout = 0, pid = 1559

C_cout = 4, p_cout = 1, pid = 1558

C_cout = 4, p_cout = 1, pid = 1560

C_cout = 3, p_cout = 2, pid = 1557

C_cout = 4, p_cout = 1, pid = 1562

C_cout = 3, p_cout = 2, pid = 1561

C_cout = 4, p_cout = 1, pid = 1566

C_cout = 3, p_cout = 2, pid = 1565

C_cout = 3, p_cout = 2, pid = 1569

C_cout = 2, p_cout = 3, pid = 1568

C_cout = 4, p_cout = 1, pid = 1574

C_cout = 3, p_cout = 2, pid = 1573

C_cout = 3, p_cout = 2, pid = 1577

C_cout = 2, p_cout = 3, pid = 1576

C_cout = 3, p_cout = 2, pid = 1581

C_cout = 2, p_cout = 3, pid = 1580

C_cout = 2, p_cout = 3, pid = 1584

C_cout = 1, p_cout = 4, pid = 1583

C_cout = 3, p_cout = 2, pid = 1563

C_cout = 2, p_cout = 3, pid = 1556

C_cout = 2, p_cout = 3, pid = 1564

C_cout = 2, p_cout = 3, pid = 1570

C_cout = 1, p_cout = 4, pid = 1555

C_cout = 3, p_cout = 2, pid = 1575

C_cout = 2, p_cout = 3, pid = 1572

C_cout = 2, p_cout = 3, pid = 1578

C_cout = 1, p_cout = 4, pid = 1571

C_cout = 2, p_cout = 3, pid = 1582

C_cout = 1, p_cout = 4, pid = 1579

C_cout = 1, p_cout = 4, pid = 1585

C_cout = 0, p_cout = 5, pid = 1554

By reasoning: By referencing a network article, you can get:

If F (n) is set, it indicates the number of processes generated by the entire program when the program executes N cycles. It is easy to obtain the recursive formula:

F (n) = 1 + f (n-1) + f (n-2) + f (n-3) +... + F (0)

For example, for I = 0; I <n; I ++ <p>

Because the sub-process of Fork () at I = 0 will continue loop n-1 times next time, the sub-process of Fork () at I = 1 will only need to loop N-2 times next time ....

The constant 1 is the process itself.

Boundary condition, F (0) = 1

In this way, we get the answer to the question:

F (n) = 1 + f (n-1) + f (n-2) +... + F (0)

F (0) = 1

Here we can find the closed form:

F (0) = 1

F (1) = 2

F (2) = 4

...

Using mathematical induction, we can obtain F (n) = 2 ^ n.

Therefore, for program 1, 2 ^ 5-1 = 31 rows are printed.

For program 2, a total of 2 ^ 5 = 32 processes are generated.

However, I still don't know why the results of the two variables are output in that form. Thank you for your guidance !!!

Below is a piece of interesting code:

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

We need to know the & and | operators. & There is a short circuit.

A & B. If a = 0, it is unnecessary to continue executing & B; if A is not 0, it is necessary to continue executing & B.
A | B. If a is not 0, it is unnecessary to continue | B, and a = 0, it is necessary to continue | B.

We can get the following through drawing:

In addition to the previous fork and the final fork, a total of 4*5 = 20 processes, except the main process, 19 processes.

More articles, welcome to pay attention to http://blog.csdn.net/wallwind copyright owned by the blogger ~~ Commercial use prohibited

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.