The following program, namely fork () to find the prime number change:
Experiment 1 The parent process does not sleep, and 201 child processes sleep
#include <unistd.h>
#include <sys/types.h>
#include <stdlib.h>
#include <stdio.h>
#define LEFT 200
#define RIGHT 250
int main(void)
{
int i,j,mark;
pid_t pid;
for(i = LEFT; i <= RIGHT; i++)
{
pid = fork();
if(pid < 0)
{
fprintf(stderr,"fork() failed!\n");
exit(1);
}
else if(pid == 0)//child
{
mark = 1;
for(j = 2; j < i/2; j++)
{
if(i % j ==0)
{
mark = 0;
break;
}
}
if(mark)
printf("%d is a primer\n",i);
sleep(1000);
exit(0);//!!!
}
}
exit(0);
}
Change: Sleep for 1000 seconds before each child process ends. In this case, the parent process must end first, and after 201 child processes end. In this case, the parent process directly exit() after creating 201 child processes, and the child process sleeps after finishing its work.
ps axf view process status:
mhr@ubuntu:~/Desktop/xitongbiancheng/test$ ps axf
15800 pts/2 S 0:00 \_ ./a.out
15801 pts/2 S 0:00 \_ ./a.out
15802 pts/2 S 0:00 \_ ./a.out
15803 pts/2 S 0:00 \_ ./a.out
15804 pts/2 S 0:00 \_ ./a.out
15805 pts/2 S 0:00 \_ ./a.out
15806 pts/2 S 0:00 \_ ./a.out
15807 pts/2 S 0:00 \_ ./a.out
15808 pts/2 S 0:00 \_ ./a.out
15809 pts/2 S 0:00 \_ ./a.out
15810 pts/2 S 0:00 \_ ./a.out
15811 pts/2 S 0:00 \_ ./a.out
15812 pts/2 S 0:00 \_ ./a.out
15813 pts/2 S 0:00 \_ ./a.out
15814 pts/2 S 0:00 \_ ./a.out
15815 pts/2 S 0:00 \_ ./a.out
15816 pts/2 S 0:00 \_ ./a.out
15817 pts/2 S 0:00 \_ ./a.out
15818 pts/2 S 0:00 \_ ./a.out
15819 pts/2 S 0:00 \_ ./a.out
15820 pts/2 S 0:00 \_ ./a.out
...
...
...
You can see that all the 201 child processes are written by the top grid, so the parent process of the 201 process is the init process
For all processes whose parent process has terminated, their parent process is changed to init process, we call these processes adopted by init process. The operation process is roughly as follows: When a process A terminates, the kernel will check all other active processes BCD...etc. to determine whether these active processes are child processes of terminating process A, and if so, the parent of the active process The process is changed to 1 (the ID of the init process is 1). This approach ensures that every process has a parent process.
Experiment 2 The parent process sleeps, the child process does not sleep
#include <unistd.h>
#include <sys/types.h>
#include <stdlib.h>
#include <stdio.h>
#define LEFT 200
#define RIGHT 250
int main(void)
{
int i,j,mark;
pid_t pid;
for(i = LEFT; i <= RIGHT; i++)
{
pid = fork();
if(pid < 0)
{
fprintf(stderr,"fork() failed!\n");
exit(1);
}
else if(pid == 0)//child
{
mark = 1;
for(j = 2; j < i/2; j++)
{
if(i % j ==0)
{
mark = 0;
break;
}
}
if(mark)
printf("%d is a primer\n",i);
exit(0);//!!!
}
}
sleep(1000);
exit(0);
}
mhr@ubuntu:~/Desktop/xitongbiancheng/test$ ps axf
\_ zeitgeist-datahub
2824 ? Sl 0:37 \_ /usr/bin/python /usr/bin/terminator
2836 ? S 0:00 | \_ gnome-pty-helper
2837 pts/0 Ss 0:01 | \_ /bin/bash
16001 pts/0 R+ 0:00 | | \_ ps axf
2858 pts/2 Ss 0:00 | \_ /bin/bash
15944 pts/2 S+ 0:00 | \_ ./a.out
15945 pts/2 Z+ 0:00 | \_ [a.out] <defunct>
15946 pts/2 Z+ 0:00 | \_ [a.out] <defunct>
15947 pts/2 Z+ 0:00 | \_ [a.out] <defunct>
15948 pts/2 Z+ 0:00 | \_ [a.out] <defunct>
15949 pts/2 Z+ 0:00 | \_ [a.out] <defunct>
15950 pts/2 Z+ 0:00 | \_ [a.out] <defunct>
15951 pts/2 Z+ 0:00 | \_ [a.out] <defunct>
15952 pts/2 Z+ 0:00 | \_ [a.out] <defunct>
15953 pts/2 Z+ 0:00 | \_ [a.out] <defunct>
15954 pts/2 Z+ 0:00 | \_ [a.out] <defunct>
15955 pts/2 Z+ 0:00 | \_ [a.out] <defunct>
15956 pts/2 Z+ 0:00 | \_ [a.out] <defunct>
15957 pts/2 Z+ 0:00 | \_ [a.out] <defunct>
15958 pts/2 Z+ 0:00 | \_ [a.out] <defunct>
...
....
....
3692 ? Sl 0:02 \_ /usr/lib/x86_64-linux-gnu/notify-osd
In this experiment, since the parent process did not exit, the parent process of all child processes is still the previous parent process and is not transferred to the init process.
It can be seen that the process status of the 201 child processes at this time is Z+, which is the zombie process. So what is a zombie process and how are zombie processes generated?
In UNIX terminology, a process that has been terminated, but its parent process has not yet dealt with it (obtain information about terminating the child process, and release the resources it still occupies) becomes a zombie process.
So for the above example, the parent process forks 201 child processes. Unless the parent process waits to obtain the termination status of the child process, these child processes will become zombie processes after termination, as above. Regarding the aftermath of the child process, use wait()/waitpid() to deal with it, which will be explained in detail in the next section.
One more note, what happens when a process adopted by the init process terminates? Will he become a zombie process?
The answer is no. The init process is designed so that whenever a child process terminates, init will call a wait() function to deal with it and get its termination status. This prevents the system from being filled with zombie processes.