One, the process replicates (or produces)
The child processes obtained by using the fork function inherit the entire process's address space from the parent process, including: process context, process stack, memory information, open file descriptor, signal control settings, process priority, process group number, current working directory, root directory, resource limit, control terminal, and so on.
The difference between a child process and a parent process is:
1, the parent process set the lock, the child process does not inherit (because if it is an exclusive lock, is inherited, contradictions)
2, the respective process ID and the parent process ID are different
3. The pending alarm of the sub-process is cleared;
4. The pending signal set of the sub-process is set to empty.
Two, fork system call
Include header files <sys/types.h> and <unistd.h>
function function: Create a child process
Function prototypes
pid_t fork (void); A two-time return value is returned in the respective address space, meaning that there are now two basic processes executing
Parameters: No parameters.
return value:
- If a child process is created successfully, the child process ID is returned for the parent process
- If a child process is created successfully, the return value is 0 for the child process
- If 1 indicates that the creation failed
Flow chart:
The parent process calls the fork () system call and then falls into the kernel, making the process copy, if successful:
1, the return value for the calling process, the parent process, is the newly generated subprocess PID, because the process PCB has no child process information, and the parent process can only be obtained by doing so.
2, the child process (the new process that was just created) returns 0,
At this point, there are two processes executing down
If it fails, it returns 0, and the calling process continues to execute down
Note: Fork in English means: Branch, fork system call replication produces a child process that is basically the same as the parent process (the calling process): The code snippet + data segment + stack segment +PCB, the current run environment is basically the same, so the child process begins to execute down after the fork and does not start from scratch.
Sample program:
#include <stdio.h>#include<unistd.h>#include<stdlib.h>#defineErr_exit (M) Do{perror (M); Exit (Exit_failure); } while(0)intMainvoid) {pid_t pid; printf ("before calling fork,calling process pid =%d\n", Getpid ()); PID=Fork (); if(PID = =-1) Err_exit ("Fork Error"); if(PID = =0) {printf ("This is the child process and the child's pid =%d,parent ' s pid =%d\n", Getpid (), Getppid ()); } if(PID >0){ //sleep (1);printf"This is the parent process and PID =%d, child ' s PID =%d\n", Getpid (), PID); } return 0;}
Operation Result:
When no sleep is given to the parent process, because the parent process executes first, the child process becomes the orphan process, and the system Tuogu it to the 1 (init) process.
So ppid = 1.
When you add sleep, the child process finishes first:
This time you can see the results you want right.
Third, orphan process, zombie process
After the fork system is called, the parent-child process is executed alternately, in a variable order.
If the parent process exits first and the child process does not exit then the parent process of the child process becomes the init process (Tuogu to the init process). (Note: Any process must have a parent process)
If the child process exits first and the parent process does not exit, the child process must wait until the parent process captures the exit state of the child process to really end, otherwise the child process becomes zombie process (zombie process: leaving only some exit information for the parent process to query)
Example:
#include <stdio.h>#include<unistd.h>#include<stdlib.h>#defineErr_exit (M) Do{perror (M); Exit (Exit_failure); } while(0)intMainvoid) {pid_t pid; printf ("before calling fork,calling process pid =%d\n", Getpid ()); PID=Fork (); if(PID = =-1) Err_exit ("Fork Error"); if(PID = =0) {printf ("This is the child process and the child's pid =%d,parent ' s pid =%d\n", Getpid (), Getppid ()); } if(PID >0) {Sleep ( -); printf ("This is the parent process and PID =%d, child ' s PID =%d\n", Getpid (), PID); } return 0;}
The above procedure is basically consistent with the previous one, that is, let the parent process sleep 100 seconds, so that the child process first exit
Operation Result:
As can be seen, the child process exits first, but the process list can also be viewed to the child process, [a.out] <defunct>, dead meaning, the zombie process, if there are too many zombie processes in the system, will make the new process can not be generated.
Four, copy when writing
Linux system in order to improve system performance and resource utilization, the system does not actually replicate a copy when fork out a new process.
Replication is unnecessary if multiple processes are to read copies of their own portion of the resource.
Each process simply saves a pointer to the resource.
If a process modifies a "copy" of its own resource, that resource is copied. That's what it means when it's written.
Fork and Vfork:
Before the fork has implemented copy on write. UNIX designers are concerned about the waste of address space caused by exec immediately after fork, so the vfork system call is introduced.
Vfork has a limit, the child process must immediately execute the _exit or EXEC function.
Even if the fork implements copy on write, the efficiency is not vfork high, but we do not recommend the use of vfork, because almost every vfork implementation, there are more or less a certain problem
Vfork:
Linux Description
Vfork (), Just like fork (2), creates a child process of the calling pro-
Cess. For details and return value and errors, see Fork (2).
vfork () is A special case of Clone (2) . It's used to create new pro-
&NBSP;&NB sp; cesses without copying the page tables of the parent process. it may
be useful in performance-sensitive applications where a child would be
created which then Immediately issues an EXECVE (2).
Vfork () differs from fork (2) and the parent is suspended until the
Child terminates (either normally, by calling _exit (2), or abnormally,
After delivery of a fatal signal), or it makes a call to Execve (2).
Until, the child shares all memory with its parent, includ-
ing the stack. The child must not return from the current function or
Call Exit (3), but could call _exit (2).
Signal handlers is inherited, but is not shared. Signals to the parent
Arrive after the child releases the parent's memory (i.e., after the
Child terminates or calls Execve (2)).
Sample program:
#include <stdio.h>#include<unistd.h>#include<stdlib.h>#defineErr_exit (M) Do{perror (M); Exit (Exit_failure); } while(0)intMainvoid) {pid_t pid; intval =1; printf ("before calling fork, val =%d\n", Val); //pid = fork ();PID =vfork (); if(PID = =-1) Err_exit ("Fork Error"); if(PID = =0) {printf ("Chile Process,before Change val, val =%d\n", Val); Val++; //sleep (1);printf"This is the child process and val =%d\n", Val); _exit (0); } if(PID >0) {Sleep (1); //val++;printf"This is parent process and val =%d\n", Val); } return 0;}
When Fork is called:
Operation Result:
Copy when writing
When using vfork but the child process does not exit with exit:
The result is wrong,
To exit with Vfork and exit:
void sigusr1 (int sig) { printf ("Get Signal\n");} int main () { int pid; int ppid; if (Signal (sigrtmin, sigusr1) = = Sig_err) { perror ("Can not catch sigrtmin!"); } if ((Pid=fork ()) = =-1) perror ("fork error!"); else if (PID = = 0) /*child deal*/ { sleep (1); Ppid = Getppid (); Kill (Ppid, sigrtmin); } if ((Pid=fork ()) = =-1) perror ("fork"); else if (PID = = 0) /*child deal*/ { ppid = Getppid (); Kill (Ppid, sigrtmin); Sleep (2); } Sleep (3); return 0;}
Output THREE times!!!!!
Linux system call Fork () Summary (ii)