Linux僵尸进程是指一个已经结束运行但尚未被其父进程回收资源的子进程。在Linux系统中,当一个进程终止时,操作系统会将其从进程表中移除,并释放大部分资源。然而,如果父进程没有正确地读取子进程的退出状态(通过wait()或waitpid()系统调用),子进程的进程描述符和资源(如内存、文件描述符等)仍然保留在系统中,这时子进程就变成了僵尸进程。
假设我们有一个简单的C程序,创建一个子进程并让子进程立即退出,而父进程没有调用wait()或waitpid()来读取子进程的退出状态。
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
int main() {
pid_t pid = fork();
if (pid == -1) {
perror("fork");
exit(EXIT_FAILURE);
}
if (pid == 0) {
// 子进程
printf("Child process exiting...\n");
exit(0);
} else {
// 父进程
printf("Parent process not waiting for child...\n");
// 父进程没有调用wait()或waitpid()
}
return 0;
}
运行这个程序,你会看到子进程退出并变成僵尸进程。可以使用ps命令查看僵尸进程:
ps aux | grep Z
你会看到类似以下的输出:
user 12345 0.0 0.1 22984 6448 ? Zs 12:34 0:00 [child_process] <defunct>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
int main() {
pid_t pid = fork();
if (pid == -1) {
perror("fork");
exit(EXIT_FAILURE);
}
if (pid == 0) {
// 子进程
printf("Child process exiting...\n");
exit(0);
} else {
// 父进程
int status;
printf("Parent process waiting for child...\n");
waitpid(pid, &status, 0); // 等待子进程退出
}
return 0;
}
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <sys/wait.h>
void sigchld_handler(int signum) {
int status;
pid_t pid;
while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
printf("Child process %d exited with status %d\n", pid, WEXITSTATUS(status));
}
}
int main() {
pid_t pid = fork();
if (pid == -1) {
perror("fork");
exit(EXIT_FAILURE);
}
if (pid == 0) {
// 子进程
printf("Child process exiting...\n");
exit(0);
} else {
// 父进程
struct sigaction sa;
sa.sa_handler = sigchld_handler;
sigemptyset(&sa.sa_mask);
sa.sa_flags = SA_RESTART;
if (sigaction(SIGCHLD, &sa, NULL) == -1) {
perror("sigaction");
exit(EXIT_FAILURE);
}
printf("Parent process not waiting for child...\n");
// 父进程继续执行其他任务
}
return 0;
}
通过这些方法,可以有效地避免僵尸进程的产生,确保系统资源的合理利用。