Fork that little thing Fork Summary
Fork () Creates a new process by copying the calling process. Under Linux, fork () is implemented by using a write-time copy page, so its only disadvantage is that it replicates the time and memory of the parent page table and creates a unique task structure for the child process.
One of the wonders of fork invocation is that it is only invoked once, but it can return two times, and it has 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;
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 that do not have a fixed sequence of priorities, and which process executes the process scheduling strategy to see the system first. After fork, the variables of the two processes are independent and exist in different addresses.
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. Parent-child process different point
1 The child process has its own unique process ID, and this ID is not the same as the ID in any current process group.
2 The child process does not inherit the memory lock of the parent process (Mlock (2), Mlockall (2)).
3 The Child Process resource utilization (Getrusage (2)) and the CPU Time counter (number (2)) are reset to zero.
4 the pending signal set of the child process is initially empty (sigpending (2)).
5) The subkey does not inherit semaphore adjustments from the parent process item (SEMOP (2)).
6 The child process does not inherit the record lock from the parent process (FCNTL (2)).
7 The child process does not inherit the timer from its parent process (Setitimer (2), Alarm (2), Timer_create (2)).
8 The subprocess does not inherit the unfinished asynchronous I/O operations from the parent (Aio_read (3), Aio_write (3)), nor does it inherit any asynchronous I/O contexts from the parent level.
9 The subprocess does not inherit the directory change notification (dnotify) from its parent process (see f_notify description in Fcntl (2))
10 The SIGCHLD signal is emitted after the child process terminates.
11) The Port access rights set by Ioperm (2) are not inherited by the quilt process; The child process must use Ioperm to open any bits it needs
12 If a thread of the process calls the fork () function, the entire virtual address space of the parent process is replicated in the child, including the state mutex, the condition variable and other thread objects (pthreads);(can use Pthread_atfork (3) To limit the replication scope). resources that the child process can inherit from the parent process
1 A copy of a set of open file descriptors inherited by the child process (reference open (2))
2 copy of a set of open message queue descriptors that the subprocess inherits from parents (reference Mq_overview (7))
3 The child process inherits a copy of the directory stream set opened by the parent (Opendir (3)) similarities and differences between fork and Vfork
1) vfork () Just like fork (2) creates a subprocess for the calling process.
2) Vfork () is a special case of Clone (2). It is used to create a new process without copying the page table of the parent process. It may be useful in performance-sensitive applications after the child process is created, and then immediately run a execve ().
3 The difference between vfork () and fork (2) is that the calling thread is suspended until the child process terminates (usually by calling _exit (2), or after the fatal signal is transmitted), or by calling Execve2. Until then, the child shares all memory with the parent, including the stack. The child must not return or call exit (3) from the current function, but can call _exit (2).
4) As with fork (2), a subprocess created by Vfork () inherits a copy of the various callers ' process attributes (for example, file descriptors, signal disposition, and current working directory). Vfork () calls differ only in the processing of virtual address space.
Test Code
Here I will first analyze the following examples, followed by examples in the process of communication, thread pool, process synchronization will be accompanied by examples. This time we'll go into the fork () function. The variables for the fork () process are independent, exist in different addresses, and are not shared
#include <unistd.h>
#include <stdio.h>
intmain (void)
{
int i=0;
pid_t Rpid;
int count=0;
Rpid=fork ();
if (rpid<0) {
return-1;
}
if (rpid==0) {
printf ("Child %d%d%d\n", Getpid (), Getppid (), rpid);
count++; Child process Add Count
} else{
printf ("Parent%d%d%d\n", Getpid (), Getppid (), rpid);
count=100; Parent process assign to Count
}
printf ("pid%d,%d\n", Getpid (), count),//print process ID and count value; return
0;
}
Run Result:
parent1417 1095 1418
pid1417,100
Child 1418 1 0
PID 1418,1
From the results of the run, you can see that the parent process runs first, and if the child process does not have a parent process, then its parent process ID will be 1. Also, Count is not the same as the value of the parent process and the child process. The parent process count is 100, and the child process count is 1. An analysis of the number of calls and numbers of fork () functions two times fork ()
#include <unistd.h>
#include <stdio.h>
intmain (void)
{
int i=0;
pid_t Rpid;
Rpid=fork ();
if (rpid<0) {
return-1;
}
if (rpid==0)
printf ("Child %d%d%d\n", Getpid (), Getppid (), rpid);
else
printf ("Parent%d%d%d\n", Getpid (), Getppid (), rpid);
Rpid=fork ();
if (rpid<0) {
return-1;
}
if (rpid==0)
printf ("Child %d%d%d\n", Getpid (), Getppid (), rpid);
else
printf ("Parent%d%d%d\n", Getpid (), Getppid (), rpid);
return 0;
}
Test results
parent1689 1095 1690
Child 1690 1689 0
Parent 1689 1095 1691
Parent 1690 1 1692
Child 1691 1 0
Child 1692 1 0
As you can see from the test results, process 1689 generates 1690 child processes for the first call to the fork process. And then call the second fork. 1689 generates a child process of 1691, and the parent process ID of the subprocess is reset to 1 because the system runs the parent process first. The first generated subprocess also calls the second fork function to generate child process 1692. Similarly, the parent process runs first, and the child process 1692 's parent process is also set to 1. As shown in the following illustration:
three times fork ()
#include <unistd.h>
#include <stdio.h>
intmain (void)
{
int i=0;
pid_t Rpid;
Rpid=fork ();
if (rpid<0) {
return-1;
}
if (rpid==0)
printf ("Child %d%d%d\n", Getpid (), Getppid (), rpid);
else
printf ("Parent%d%d%d\n", Getpid (), Getppid (), rpid);
Rpid=fork ();
if (rpid<0) {
return-1;
}
if (rpid==0)
printf ("Child %d%d%d\n", Getpid (), Getppid (), rpid);
else
printf ("Parent%d%d%d\n", Getpid (), Getppid (), rpid);
Rpid=fork ();
if (rpid<0) {
return-1;
}
if (rpid==0)
printf ("Child %d%d%d\n", Getpid (), Getppid (), rpid);
else
printf ("Parent%d%d%d\n", Getpid (), Getppid (), rpid);
return 0;
}
Run Result:
parent1842 1095 1843
Parent 1842 1095 1844
Parent 1842 1095 1845
Child 1843 1842 0
Child 1845 1 0
Parent 1843 1 1846
Child 1844 1 0
Child 1846 1843 0
Parent 1843 1 1847
Parent 1844 1 1848
Child 1847 1 0
Child 1848 1 0
Parent 1846 1 1849
Child 1849 1 0
From the results above, the main process 1842 always takes precedence. 3 times fork was invoked during execution. The first fork generates 1843 processes, the second fork generates 1844 processes, and the third fork generates 1845 processes. The next 1843 runs the second fork and the third fork generates process 1846 and process 1847, respectively. The 1846 process again runs the last fork build 1849. The 1844 process generated by the second fork of the total process runs the third Fork build sub process 1848. Process 1845 is a process that invokes a fork-generated subprocess, because the program has no fork, so it has no child processes. The relationship of the process is shown in the following illustration:
The total number of processes and the relationship to call Fork
The total number of processes that can be deduced from mathematical deduction is the relationship between the call fork and the F (N) = 2^n. reference materials
1.man Fork