博创网站建设团队,新闻类网站的设计,中国网站排名 优帮云,南通网站流量优化在 Unix 进程模型中#xff0c;父进程和其所产生的子进程是异步运行的#xff0c;所以如果子进程在结束后#xff0c;会留下一些信息需要父进程使用 wait / waitpid 来接收。而如果父进程太忙了#xff0c;没有调用 wait / waitpid 的话#xff0c;子进程就会变成… 在 Unix 进程模型中父进程和其所产生的子进程是异步运行的所以如果子进程在结束后会留下一些信息需要父进程使用 wait / waitpid 来接收。而如果父进程太忙了没有调用 wait / waitpid 的话子进程就会变成僵尸进程。僵尸进程不可能被杀死因为它已经死了不存在再死一次的问题。死的对立面是活死者已死。只有活的进程才可能被杀死。什么是僵尸进程首先要明确一点僵尸进程的含义是子进程已经死了但是父进程还没有wait它的一个中间状态这个时候子进程是一个僵尸。正常情况下子死父wait清理掉子进程的task_struct释放子进程的PID:#include pthread.h
#include stdio.h
#include stdlib.h
#include unistd.h
#include pthread.h
#include semaphore.hint main(void)
{pid_t pid,wait_pid;int status;pid fork();if(pid 1){perror(Cannot create new process\n);exit(1);}else if(pid 0){printf(child process id:%ld\n,(long)getpid());pause();_exit(0);}else{#if 0printf(ppid :%d\n,getpid());while(1);#endifdo{wait_pid waitpid(pid,status,WUNTRACED | WCONTINUED);if(WIFEXITED(status))printf(child process is killed by signal %d\n,WIFSIGNALED(status));}while(!WIFEXITED(status) !WIFSIGNALED(status));exit(0);}
}
执行gcc ps_wait.c -pthread ./a.out
执行情况如下linuxubuntu:~/linux$ gcc ps_wait.c -pthread ./a.out
child process id:4578每次执行生成的子进程会不同这里只是举例子说明运行我们看到2个a.out进程杀死子进程4578看到父进程的打印之后,4578会消失因为父进程执行到了wait也知道了子进程是被信号2杀掉的。但是如果子进程死了父进程不执行到wait比如把上图中的#if 0改为#if 1杀死子进程后子进程就会是一个僵尸注意这里说的是子进程会变成一个僵尸进程代码如下#include pthread.h
#include stdio.h
#include stdlib.h
#include unistd.h
#include pthread.h
#include semaphore.hint main(void)
{pid_t pid,wait_pid;int status;pid fork();if(pid 1){perror(Cannot create new process\n);exit(1);}else if(pid 0){printf(child process id:%ld\n,(long)getpid());pause();_exit(0);}else{#if 1printf(ppid :%d\n,getpid());while(1);#endifdo{wait_pid waitpid(pid,status,WUNTRACED | WCONTINUED);if(WIFEXITED(status))printf(child process is killed by signal %d\n,WIFSIGNALED(status));}while(!WIFEXITED(status) !WIFSIGNALED(status));exit(0);}
}
我们重新运行当我们用kill -2杀掉子进程4628后我们发现4628成为一个僵尸状态变为Z名字上也加了一个棺材[]成为[a.out]Z表示的是僵尸进程[]符号就像一口棺材一样把这个僵尸进程给装了起来僵尸不可能被杀死?我们看到上面4628是个僵尸很不爽所以我们想把它干掉据说Linux有个信号9神挡杀神佛挡杀佛我们现在来用kill -9干掉4628从上图可以看出我们把4628用kill -9捅了好多刀但是最后看4628这个僵尸还是没有消失。因为僵尸已经是死了它不可能再次被杀死你给它捅一万刀它也是个死人不可能再次死僵尸不可能被杀死因为它已经死了两种方法来清理僵尸进程1、只等父进程来wait清理尸体了。2、这个时候我们能够把僵尸消失掉的方法就是杀死僵尸进程的父进程4627。一个僵尸可以被杀死的假象下面的这个程序证明「僵尸可以被杀死」这样的假象。#include pthread.h
#include stdio.h
#include stdlib.h
#include unistd.h
#include pthread.h
#include semaphore.hstatic void *thread_fun(void *param)
{while(1);
}int main(void)
{pthread_t tid;int ret;ret pthread_create(tid,NULL,thread_fun,NULL);if(ret -1){perror(cannot create new thread\n);return -1;}pthread_exit(0);return 0;
}
我们在主线程里面pthread_create()创建线程后pthread_exit()退出这个时候我们会发现在ps命令里面,a.out显示为一个僵尸进程。这个僵尸进程出现是我们在thread_fun 里面写了一个while(1)不能退出导致的。继续开始我们的表演我们使用下面的命令来杀死这个僵尸进程。kill -9 4730我们会惊奇地发现4730真地会从ps命令里面消失。在没有执行命令杀死 4730 之前我们「猜测」能杀死僵尸的本质原因是,当主线程4730调用pthread_exit()退出后主线程4730的状态确实是僵尸了但是该进程里面的4731线程却没有死。我们看看proc 文件系统下面的进程状态看看4731:4731是活着的证明整个进程并没有挂。所以4730的退出只是让整个进程半死。而由于ps这些命令的误会4730凑巧又是整个进程的PID它显示地好像整个4370成了僵尸一样。4731这个子进程什么时候死了呢那么根据POSIX标准关于信号(signal)的定义当我们执行kill -9 4730 (4730是4730和4731的TGID也是整个进程用户态视角的PID)的时候是要杀死整个4730进程的所以这个时候4731被我们杀死整个进程就都死了这个时候执行到父进程的wait逻辑导致僵尸消失。所以在本例中kill -9 4730看起来是杀死了僵尸”实际是杀死了4730整个进程里面的每个线程导致整个进程死。在此之前整个进程实际还是活的。扫码或长按关注回复「篮球的大肚子」进入技术群聊