Ubuntu中的僵尸進程(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 {
// 父進程
printf("Parent process waiting for child.
");
// 父進程沒有調用wait()或waitpid()
sleep(10);
}
return 0;
}
如果父進程在子進程之前退出,并且沒有正確地處理子進程的退出狀態,子進程也會變成僵尸進程。
如果父進程由于信號或其他原因異常退出,而沒有機會調用wait()
或waitpid()
,子進程也會變成僵尸進程。
在多線程程序中,如果主線程沒有正確地處理子線程的退出狀態,也可能導致僵尸進程的產生。
wait()
或waitpid()
:確保父進程在子進程結束后調用wait()
或waitpid()
來讀取子進程的退出狀態。SIGCHLD
),并在信號處理程序中調用wait()
或waitpid()
。fork()
和exec()
組合:在某些情況下,可以使用fork()
和exec()
的組合來避免僵尸進程的產生。#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <signal.h>
#include <unistd.h>
void sigchld_handler(int signum) {
pid_t pid;
int status;
while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
printf("Child process %d exited with status %d.
", pid, WEXITSTATUS(status));
}
}
int main() {
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);
}
pid_t pid = fork();
if (pid == -1) {
perror("fork");
exit(EXIT_FAILURE);
} else if (pid == 0) {
// 子進程
printf("Child process exiting.
");
exit(EXIT_SUCCESS);
} else {
// 父進程
printf("Parent process waiting for child.
");
sleep(10);
}
return 0;
}
通過上述方法,可以有效地避免僵尸進程的產生。