(1) Fork system call Description
The fork system call is used to create a new process from an existing process called a child process, and the original process is called the parent process. The fork is called once, returned two times, and the two returns return their respective return values, where the return value in the parent process is the process number of the child process, and the return value in the child process returns 0. Therefore, you can determine whether the process is a parent or child process by returning a value.
The child process obtained by using the fork function is a replica of the parent process, which inherits the entire process's address space from the parent process, including the process context, process stack, memory information, open file descriptor, signal control setting, process priority, process group number, current working directory, root directory, resource limit, control terminal, etc. , and the child process is unique only to its process number, timer, and so on. As a result, it can be seen that the cost of using a fork system call is large, which replicates the majority of the data and stack segments in the parent process, making the fork system call execution fast.
The return value of fork is designed for a reason, fork returns 0 in the subprocess, the child process can still call the Getpid function to get its own process ID, or it can call the Getppid function to get the process ID of the parent process. Use the Getpid function in the parent process to get its own process ID, but to want the process ID of the child process, only the return value of the fork is recorded, there is no other way.
Another feature of fork is that all file descriptors opened by the parent process are copied into the child process. The same numbered file descriptors in the parent and child processes point to the same file struct in the kernel, which means that the reference count of the file struct is incremented.
Because the code snippet (the execution code that is loaded into memory) is read-only in memory, the parent-child process can share the code snippet, and the data segment and the stack satin process are copied completely from the parent process.
2) Actions done when the parent process makes a fork system call
Assuming Id=fork (), when the parent process makes a fork system call, the fork works as follows:
① allocates the TASK_STRUCT task structure body space for the new process.
② Copy the parent process task_struct the task structure to the child process task_struct task structure body.
③ establishes the kernel stack for the new process in its memory.
④ initializes settings for a subset of variables in the TASK_STRUCT task structure of a child process.
⑤ copies the information about the parent process to the child process and establishes a sharing relationship.
The ⑥ process is added to the operational queue.
⑦ ends The fork () function, returning the child process ID value to the stack segment variable ID in the parent process.
⑧ when a child process starts running, the operating system returns 0 to the sub-process stack segment variable ID.
(3) What happens when the fork is called
The following code is a fork function call template, which is often used in conjunction with the If-else statement to make the parent-child process perform a different process. Assuming that the following code executes the X process, which is the XX process after the fork is generated, the process ID number of the XX process is 1000.
int pid;
PID = fork ();
if (PID < 0) {
Perror ("fork failed");
Exit (1);
}
if (PID = = 0) {
Message = "This is the child/n";
Before calling fork, in memory only x process, 12-9, at this time the XX process is not "born".
Figure 12-9 the memory before fork
After calling fork, there are not only X processes (parent processes) in memory, but also XX processes (child processes). When you fork, the system copies the entire stack segment of the parent process (except the code snippet, the code snippet, the parent-child process is shared) to the child process, and the X process and the XX process are two separate processes after the copy is completed.
As shown in 12-10, except that the variable ID value in the x process stack is now 1000, and the variable ID value in the XX process stack is 0. When the fork call is complete, the X process is returned to the user state by the system. Thereafter, both the X process and the XX process each need to proceed from the code point pointed to by their own code snippet pointer, the parent process X executes down the ID is greater than 0, so the execution of a program segment greater than 0, and the child process xx down execution of the judgment ID equals 0, so the execution equals 0 of the program segment.
Figure 12-10 the memory after fork
4) Fork function prototype
|
#include <sys/ Types.h> //provides the definition of type pid_t #include <unistd.h> |
|
|
|
pid_t fork (void) |
function return value |
0: return to Child process |
The ID of the child process (an integer greater than 0): returned to the parent process |
-1: Error, returned to parent process, error reason stored in errno |
error code |
eagain: Out of memory |
|
(5) Use example of fork function
FORK.C source code is as follows:
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
int main (void)
{
pid_t pid;
Char *message;
int n;
PID = fork ();
if (PID < 0) {
Perror ("fork failed");
Exit (-1);
}
if (PID = = 0) {
Message = "This is the child\n";
n = 3;
} else {
Wait (0); /* Block wait for child process to return */
Message = "This is the parent\n";
n = 1;
}
for (; n > 0; n--) {
printf (message);
Sleep (1);
}
return 0;
}
Compile gcc fork.c–o fork.
Execute the./fork and execute the results as follows:
The child
The child
The child
This is the parent
The reader can change sleep (1) to sleep (30) and then view the number of processes by Ps-ef|grep fork.
(6) Two cases of the process after fork
A parent process that wants to replicate itself so that the parent and child processes execute different pieces of code at the same time. This is a common model of the network concurrency server, where the parent process waits for a service request from the client, and when such a request arrives, the parent process calls fork to let the child process handle the request, and the parent process continues to wait for the next service request.
The other is to execute another program through exec after the fork, the execution of commands on the terminal is the case, the shell process fork immediately after calling exec to execute the command.
(7) There are two common cases of processing file descriptors after fork
The parent process waits for the child process to complete. In this case, the parent process does not need to do any processing of its file descriptor, and when the child process terminates, the file offset of any shared descriptor for which it has read and write has been updated accordingly.
The parent and child processes each execute different program segments. In this case, after the fork, the parent and child processes each close the file descriptor they do not need to use, and does not interfere with the file descriptor used by the other party. This approach is often used in concurrent network servers.
8) In addition to opening the file, many other properties of the parent process are also inherited by the child process
Actual user ID, actual group ID, valid user ID, valid group ID;
Additional group ID;
Process group ID;
Session ID;
Y control terminal;
Y settings-user-id flag and set-group-id flag;
Y current working directory;
root directory;
Y file Permissions screen word;
signal shielding and arrangement;
Open file descriptor;
environment variables;
Connected shared storage segments;
Y data segment, code snippet, heap segment,. BSS segment;
Resource constraints.
(9) There are the following differences between parent and child processes
The return value of the ÿfork;
Process ID;
Y different parent process id;
The Tms_utime, Tms_stime, Tms_cutime, and tms_ustime of the child processes are set to 0;
The parent process sets the lock, and the child process does not inherit;
The unhandled alarm signal sub-process will be cleared;
The pending alarm of the child process is cleared;
The pending signal set of the child process is set to the empty.
(ten) The difference between fork and vfork
Using a fork call copies the resources owned by the parent process (process environment, stack heap, and so on) for the child process, while the vfork design requires the child process to call exec immediately without modifying any memory, and vfork the new child process to share all the resources with the parent process. It is important to note that the modification of data in a child process is the modification of the parent process data.
Using the fork system call to produce a parent-child process, by default without human intervention, the order of execution of the parent-child process is dispatched by the operating system, who first performs the uncertainty. In the case of parent-child processes generated by vfork, it is not until the child processes call _exit or exec that the parent process will wait (the parent process waits because it does not receive a correlated signal that the child process has executed).
Vfork's appearance is to solve the problem that fork wasted user space memory, because after fork, it is possible to perform the EXEC function rebirth, vfork design idea is to cancel the fork caused the duplication of the stack, using vfork can avoid the waste of resources, But it also brings the problem of resource sharing.
In Linux, the fork is optimized to invoke copy-on-write (Cow,copy on write), and when the system calls fork to generate the child process, it does not immediately replicate the parent process's resources for the child process, but instead replicates the resource when it encounters a write (modify the resource) operation. It makes an ordinary fork call very similar to vfork, but avoids the vfork disadvantage, making vfork unnecessary.
Fork system call (reprint)