Copy process fork method
Basic concepts
First, let's look at the fork method: create a child process. The process calling fork function is the parent process, and the newly generated process is the child process.
The format is:
pid_t fork(void);
Return the pid of the child process in the parent process, 0 in the child process, and - 1 in case of failure.
Illustration:
Create child process example
Example 1:
#include<stdio.h> #include<unistd.h> #include<assert.h> #include<stdlib.h> int main(void) { char* s = NULL; int n = 0; pid_t pid = fork(); assert(pid != -1); if (pid == 0) { s = "child"; n = 3; } else { s = "parent"; n = 7; } for (int i = 0; i < n; ++i) { printf("%s\n", s); sleep(1); } exit(0); }
Operation results:
Run result description: the copied child process is equivalent to copying the parent process code, and runs concurrently with the parent process. Each run result may be different.
For example, the second print result is different from the above.
getpid() and getppid()
According to the help manual:
getpid() is the ID that returns the process.
Example:
For the above example, change the output in the for loop to see what getpid() does
for (int i = 0; i < n; ++i) { printf("s = %s, pid = %d\n", s, getpid()); sleep(3); }
Running example:
getppid() returns the ID of the parent process of the current process...
Example:
for (int i = 0; i < n; ++i) { printf("s = %s, pid = %d, ppid = %d\n", s, getpid(), getppid()); sleep(3); }
Running example:
It can be seen that the pid of the child process is the ID of the parent process
fork exercise
Example:
How many A's will the following code output?
#include<stdio.h> #include<unistd.h> #include<stdlib.h> int main(void) { int i = 0; for (; i < 2; ++i) { fork(); printf("A\n"); } exit(0); }
Running example:
analysis:
Because a copy of the current program will be copied every time the loop comes in, it will be copied all the time if the for loop conditions are met
Dead process and treatment method
Concept: the child process ends before the parent process. The parent process does not call wait to obtain the child process exit code.
Dead process example
code:
Write a program that allows the child process to end first
#include<stdio.h> #include<assert.h> #include<unistd.h> #include<stdlib.h> int main(void) { char* s = NULL; int n = 0; pid_t pid = fork(); assert(pid != -1); if (pid == 0) { s = "child"; n = 3; } else { s = "parent"; n = 6; } int i = 0; for (i; i < n; ++i) { printf("s = %s, pid = %d\n", s, getpid()); sleep(3); } exit(0); }
Operation results:
The system calls the process in this state a dead process < defunct >.
Dead process processing method
The parent process uses the wait() method
Introduction:
NAME wait, waitpid, waitid - wait for process to change state SYNOPSIS #include <sys/types.h> #include <sys/wait.h> pid_t wait(int *wstatus);
WIFEXITED(wstatus) returns true if the child terminated normally, that is, by call‐ ing exit(3) or _exit(2), or by returning from main(). WEXITSTATUS(wstatus) returns the exit status of the child. This consists of the least significant 8 bits of the status argument that the child specified in a call to exit(3) or _exit(2) or as the argument for a return statement in main(). This macro should be employed only if WIFEXITED returned true. WIFSIGNALED(wstatus) returns true if the child process was terminated by a signal.
When the parent process calls wait(), it will immediately block itself. Wait will automatically analyze whether a child process of the current process has exited. If it finds such a child process that has become a zombie, wait will collect the information of the child process, destroy it completely and return; If such a child process is not found, the wait will block here until one appears.
The parameter status is used to save some states when the collected process exits. It is a pointer to type int.
Program example
#include<assert.h> #include<unistd.h> #include<stdlib.h> #include<sys/wait.h> int main(void) { char* s = NULL; int n = 0; pid_t pid = fork(); assert(pid != -1); if (pid == 0) { s = "child"; n = 3; } else { s = "parent"; n = 6; int val = 0; int id = wait(&val); if (WIFEXITED(val)) { printf("id = %d, val = %d\n", id, WEXITSTATUS(val)); } } int i = 0; for (i; i < n; ++i) { printf("s = %s, pid = %d\n", s, getpid()); sleep(3); } exit(3); }
Operation results:
First, the parent-child process runs normally
As shown in the blue box below, when the child process ends, the parent process prints the exit code of the child process.
The red line indicates that only the parent process is running now, and there is no dead process.
end
Thanks for watching~