僵尸进程是指在进程结束后,其父进程没有及时处理该进程的终止状态信息,导致该进程的进程描述符仍然存在于系统进程表中,但是已经没有实际的执行代码。这样的进程被称为僵尸进程。
僵尸进程的产生是由于父进程没有及时调用`wait()`或`waitpid()`等系统调用来获取子进程的终止状态信息。当子进程结束时,内核会将其进程描述符保留在系统进程表中,并向父进程发送一个SIGCHLD信号,通知父进程子进程已经终止。如果父进程没有处理该信号或没有主动调用`wait()`等系统调用来处理子进程的终止状态,那么僵尸进程就会产生。
如下是一个产生僵尸进程的代码
- void fork7() {
- if (fork() == 0) {
- /* Child */
- printf("Terminating Child, PID = %d\n", getpid());
- exit(0);
- } else {
- printf("Running Parent, PID = %d\n", getpid());
- while (1); /* Infinite loop */
- }
- }
其中子进程已经完成执行,但是进程表中仍然存在子进程的信息。,并显示为defunct状态,即zombie进程。
wait()
和waitpid()
是用于在父进程中等待子进程终止并获取其终止状态的系统调用函数。
这两个函数的作用包括:
等待子进程的终止:父进程可以使用wait()
或waitpid()
函数来暂停自己的执行,等待子进程结束。在子进程终止之前,父进程会一直阻塞在这个调用上。
获取子进程的终止状态:当子进程终止时,操作系统会将子进程的退出状态传递给父进程。父进程通过调用wait()
或waitpid()
来获取子进程的终止状态,并可以根据该状态进行后续处理。终止状态可以包含子进程的退出码、终止原因等信息。
pid_t wait(int* status);
status
参数用于保存子进程的终止状态。通过检查status
变量的值,父进程可以了解子进程的终止情况。wait()
函数返回已终止的子进程的PID,若出错则返回-1。pid_t waitpid(pid_t pid, int* status, int options);
pid
参数用于指定等待的子进程ID。当指定为-1时,表示等待任意一个子进程终止。status
参数用于保存子进程的终止状态。options
参数用于设置额外的选项,例如WNOHANG表示非阻塞等待。wait()
和waitpid()
函数的返回值可以提供一些信息:
示例
- void fork9() {
- int child_status;
-
- if (fork() == 0) {
- printf("HC: hello from child\n");
- } else {
- printf("HP: hello from parent\n");
- wait(&child_status);
- printf("CT: child has terminated\n");
- }
- printf("Bye\n");
- }
父进程通过使用wait函数来暂停自己的执行,等待子进程结束,在子进程终止之前,父进程会一直阻塞在这个调用上