在CentOS系统中,僵尸进程(Zombie Process)通常是由于子进程先于父进程结束,而父进程没有正确地回收子进程的资源导致的。以下是僵尸进程产生的几种常见原因:
wait()或waitpid()当子进程结束时,操作系统会将其状态设置为EXIT_ZOMBIE,并通知父进程。如果父进程没有调用wait()或waitpid()来读取子进程的退出状态,子进程就会保持僵尸状态。
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
int main() {
pid_t pid = fork();
if (pid == -1) {
perror("fork");
exit(EXIT_FAILURE);
} else if (pid == 0) {
// 子进程
printf("Child process exiting...
");
exit(EXIT_SUCCESS);
} else {
// 父进程
int status;
// 忘记调用wait()或waitpid()
printf("Parent process continuing...
");
sleep(10); // 模拟父进程继续执行其他任务
}
return 0;
}
如果父进程因为某种原因(如信号处理、崩溃等)异常退出,而没有机会调用wait()或waitpid(),子进程也会变成僵尸进程。
如果父进程长时间运行,而子进程很快结束,父进程可能没有及时回收子进程的资源。
在多线程程序中,如果主线程没有正确处理子线程的退出状态,也可能导致僵尸进程。
可以使用ps命令来检测僵尸进程:
ps aux | grep Z
输出中带有Z状态的进程就是僵尸进程。
手动杀死父进程:如果父进程还在运行,可以尝试杀死它,这样操作系统会自动回收其所有子进程的资源。
kill -9 <父进程PID>
修改代码:确保父进程正确调用wait()或waitpid()来回收子进程的资源。
使用信号处理:在父进程中设置信号处理函数,当接收到子进程退出的信号时,调用wait()或waitpid()。
以下是一个改进的示例代码,确保父进程正确回收子进程的资源:
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
int main() {
pid_t pid = fork();
if (pid == -1) {
perror("fork");
exit(EXIT_FAILURE);
} else if (pid == 0) {
// 子进程
printf("Child process exiting...
");
exit(EXIT_SUCCESS);
} else {
// 父进程
int status;
pid_t child_pid = waitpid(pid, &status, 0);
if (child_pid == -1) {
perror("waitpid");
exit(EXIT_FAILURE);
}
printf("Child process with PID %d exited with status %d
", child_pid, WEXITSTATUS(status));
}
return 0;
}
通过这种方式,可以确保子进程在退出后被正确回收,避免产生僵尸进程。