很多次碰到,或者听说过zombie/defunct process,都只是翻了一下资料,没有仔细看看这个东西。主要是涉及到了fork,signal,而这个一直没有用到,所以就懒得看。
http://en.wikipedia.org/wiki/Zombie_process,wikipedia上已经说得很明白,还有例子。对比起百度百科的说明http://baike.baidu.com/view/758736.htm,百科很多,但是大部分是堆砌和罗列。
百度上搜索到的linux zombie的相关信息,都是如何避免和解决zombie。而在开头会说明zombie如何产生,而这个是我一直都没有看明白。终于下定决心要把这个看明白一点。
以下代码在centos6.0 x86_64环境。
1. zombie.cpp 说明如何产生zombie process:
// g++ zombie.cpp -o zombie; ./zombie
// to view the zombie:
// ps axf|grep --color -in "zombie"
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <iostream>
using namespace std;
void child_progress(){
for(int i = 0; i < 5; i++){
sleep(1);
cout << "child #" << getpid() << ": in the child progress" << endl;
}
cout << "child #" << getpid() << ": exited!!!!!!!!!!!!!!!!zombie!!!!!!!!!!!!!!!!" << endl;
exit(0);
}
void main_progress(){
for(;;){
sleep(1);
cout << "parent #" << getpid() << ": in the parent progress" << endl;
}
}
int main(int argc, char** argv){
cout << "start a child progress..." << endl;
pid_t pid = 0;
pid = fork();
if(pid < 0){
cout << "create progress failed!" << endl;
exit(-1);
}
if(pid == 0){
child_progress();
}
else{
sleep(3);
main_progress();
}
return 0;
}
2. dezombie-ignore.cpp 忽略SIGCHLD信号来避免zombie:
// g++ dezombie-ignore.cpp -o dezombie-ignore; ./dezombie-ignore
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <iostream>
using namespace std;
void child_progress(){
for(int i = 0; i < 5; i++){
sleep(1);
cout << "child #" << getpid() << ": in the child progress" << endl;
}
cout << "child #" << getpid() << ": exited!no zombie!!!!!!!!!!!!!!!!" << endl;
exit(0);
}
void main_progress(){
for(;;){
sleep(1);
cout << "parent #" << getpid() << ": in the parent progress" << endl;
}
}
int main(int argc, char** argv){
cout << "ignore the SIG_CHILD signal" << endl;
if(signal(SIGCHLD, SIG_IGN) < 0){
cout << "ignore signal failed!" << endl;
exit(-1);
}
cout << "start a child progress..." << endl;
pid_t pid = 0;
pid = fork();
if(pid < 0){
cout << "create progress failed!" << endl;
exit(-1);
}
if(pid == 0){
child_progress();
}
else{
sleep(3);
main_progress();
}
return 0;
}
3.dezombie-signal.cpp 处理SIGCHLD来处理reap zombie:
// g++ dezombie-signal.cpp -o dezombie-signal; ./dezombie-signal
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <iostream>
using namespace std;
void child_progress(){
for(int i = 0; i < 5; i++){
sleep(1);
cout << "child #" << getpid() << ": in the child progress" << endl;
}
cout << "child #" << getpid() << ": exited!!!!!!!!!!!!!!!!zombie!!!!!!!!!!!!!!!!" << endl;
exit(0);
}
void main_progress(){
for(;;){
sleep(1);
cout << "parent #" << getpid() << ": in the parent progress" << endl;
}
}
void onSigChild(int sig){
int sleep_time = 10;
cout << "#" << getpid() << ": get a signal SIG_CHILD (a dead child). de-zombie in " << sleep_time << " seconds" << endl;
sleep(sleep_time);
int status;
pid_t pid = waitpid(-1, &status, WNOHANG);
if(pid < 0){
cout << "waitpid error!" << endl;
exit(-1);
}
if(pid == 0){
cout << "warning: no child terminated!" << endl;
}
cout << "child progress #" << pid << " terminated! de-zombie success!" << endl;
}
int main(int argc, char** argv){
cout << "register SIG_CHILD signal" << endl;
if(signal(SIGCHLD, onSigChild) < 0){
cout << "register signal failed!" << endl;
exit(-1);
}
cout << "start a child progress..." << endl;
pid_t pid = 0;
pid = fork();
if(pid < 0){
cout << "create progress failed!" << endl;
exit(-1);
}
if(pid == 0){
child_progress();
}
else{
sleep(3);
main_progress();
}
return 0;
}
4. dezombie-2-fork.cpp 使用两次fork来避免zombie(怎么觉得这个方法很笨拙):
// g++ dezombie-2-fork.cpp -o dezombie-2-fork; ./dezombie-2-fork
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <iostream>
using namespace std;
void child_child_progress(){
for(int i = 0; i < 5; i++){
sleep(1);
cout << "child-child #" << getpid() << ": in the child progress" << endl;
}
cout << "child-child #" << getpid() << ": exited!no zombie!!!!!!!!!!!!!!!!" << endl;
exit(0);
}
void child_progress(){
cout << "child #" << getpid() << ": start a child-child progress." << endl;
pid_t pid = 0;
pid = fork();
if(pid < 0){
cout << "create progress failed!" << endl;
exit(-1);
}
if(pid == 0){
child_child_progress();
}
else{
cout << "child #" << pid << ": terminated! the child-child progress attach to init(1) progress!" << endl;
}
}
void main_progress(){
for(;;){
sleep(1);
cout << "parent #" << getpid() << ": in the parent progress" << endl;
}
}
int main(int argc, char** argv){
cout << "start a child progress..." << endl;
pid_t pid = 0;
pid = fork();
if(pid < 0){
cout << "create progress failed!" << endl;
exit(-1);
}
if(pid == 0){
child_progress();
}
else{
cout << "parent #" << getpid() << ": wait for child to exit in 1s" << endl;
sleep(1);
int status;
waitpid(pid, &status, 0);
cout << "parent #" << getpid() << ": the child progress exited!" << endl;
main_progress();
}
return 0;
}
XP认为,代码是最好的文档。
准确点讲,应该是:精心构建的代码是最好的文档。
估计XP是假设所有代码都是精心写成的,毕竟一个人若愿意研究XP,肯定是代码基本功要过关。