本文主要是介绍Linux编程中如何避免出现僵尸进程,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
僵尸进程如何产生的?
怎样避免僵尸进程的产生
所以,避免僵尸进程的产生具有极其重要的意义。在 Linux 下,我们可以使用 ps aux | grep -w 'Z' 等命令查看系统中僵尸进程,僵尸进程的状态标记为‘Z’。一般来讲避免僵尸进程主要包含以下几种方法:
1、wait()函数的使用最为简单,源代码如图所示:
- 父进程使用wait()或者waitpid()之类的函数等待子进程退出
- 父进程先产生一个子进程,然后子进程再产生一个孙子进程,子进程在孙子进程之前退出。
- 使用信号函数sigaction为SIGCHLD设置wait处理函数。
父进程创建子进程后30s调用wait()函数,等待子进程退出,回收子进程的资源,这也意味着子进程将会成为僵尸进程30s-5s=25s。
运行该程序后,打开终端,查看进程状态,该图显示的有一个进程的标志为Z,表示该进程为僵尸进程(Zombie)。
2、两次fork()创建孙子进程
使用wait()的方法比较简洁,但是有个问题就是子进程如果处理的时间比较长的话,主进程会被挂起。比如:
对于这样的情况可以采取连续fork()两次的方法。简而言之,首先父进程首先创建子进程,子进程创建孙子进程,由孙子进程处理事务,而子进程再创建完孙子进程后,就退出。此时,孙子进程的父进程,也就是子进程退出了,因此孙子进程变为了一个孤儿进程,Linux进程处理孤儿的进程的方式,是init进程接管孤儿进程,而init进程的子进程不会成为僵尸进程。
所以上述的伪代码可以写为:
if(fork() ==0 ) { if(fork()==0) { /*孙子进程在这里处理事务*/ process(); close() exit() } else { /*子进程再这里退出,使得孙子进程成为init进程的儿子,从而避免僵尸进程的产生*/ close() exit()///<子进程在此退出 } } else { ///<爷爷进程进入下一轮的处理。 }
3、 采用信号量处理函数
还有一种方法就是采用信号量处理函数来处理这种情况,该过程的代码可以表示为:
#include
#include
#include
#include
#include
#include
int num_clients = 0;
int dead_clients = 0;
void sig_chld_handler(int sig) { pid_t pid; if (sig == SIGCHLD) { pid = wait(NULL); printf("A child dead, current child number: %d, id: %d/n", ++dead_clients, pid); }
}
int main(int argc, char **argv) { pid_t pid; signal(SIGCHLD, sig_chld_handler); for (int i = 0; i < 30; i++) { if ((pid = fork()) == 0) { exit(0); } else if (pid > 0) { printf("A child created, current child number: %d, id: %d/n", ++num_clients, pid); } } sleep(10); return 0;
}
父进程首先注册一个信号处理函数signal(SIGCHLD, sig_chld_handler),然后每当子进程退出的时候父进程都会受到SIGCHLD信号,
触发sig_chld_handler()函数,调用wait()函数等待子进程的退出。
这篇关于Linux编程中如何避免出现僵尸进程的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!