在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; } 通过这种方式,可以确保子进程在退出后被正确回收,避免产生僵尸进程。