呼叫 fork 兩次以避免僵死程序
阿新 • • 發佈:2018-11-16
分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow
也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!
當我們只fork()一次後,存在父程序和子程序。這時有兩種方法來避免產生殭屍程序:
- 父程序呼叫waitpid()等函式來接收子程序退出狀態。
- 父程序先結束,子程序則自動託管到Init程序(pid = 1)。
目前先考慮子程序先於父程序結束的情況:
- 若父程序未處理子程序退出狀態,在父程序退出前,子程序一直處於殭屍程序狀態。
- 若父程序呼叫waitpid()(這裡使用阻塞呼叫確保子程序先於父程序結束)來等待子程序結束,將會使父程序在呼叫waitpid()後進入睡眠狀態,只有子程序結束父程序的waitpid()才會返回。 如果存在子程序結束,但父程序還未執行到waitpid()的情況,那麼這段時期子程序也將處於殭屍程序狀態。
由此,可以看出父程序與子程序有父子關係,除非保證父程序先於子程序結束 或者保證父程序在子程序結束前執行waitpid(),子程序均有機會成為殭屍程序。那麼如何使父程序更方便地建立不會成為殭屍程序的子程序呢?這就要用兩次fork()了。
父程序一次fork()後產生一個子程序隨後立即執行waitpid(子程序pid, NULL, 0)來等待子程序結束,然後子程序fork()後產生孫子程序隨後立即exit(0)。這樣子程序順利終止(父程序僅僅給子程序收屍,並不需要子程序的返回值),然後父程序繼續執行。這時的孫子程序由於失去了它的父程序(即是父程序的子程序),將被轉交給Init程序託管。於是父程序與孫子程序無繼承關係了,它們的父程序均為Init,Init程序在其子程序結束時會自動收屍,這樣也就不會產生殭屍程序了。
#include <stdio.h> #include <sys/wait.h> #include <sys/types.h> #include <unistd.h> int main(void) { pid_t pid; if ((pid = fork()) < 0) { fprintf(stderr,"Fork error!/n"); exit(-1); } else if (pid == 0) /* first child */ { if ((pid = fork()) < 0) { fprintf(stderr,"Fork error!/n"); exit(-1); } else if (pid > 0) exit(0); /* parent from second fork == first child */ /* * We're the second child; our parent becomes init as soon * as our real parent calls exit() in the statement above. * Here's where we'd continue executing, knowing that when * we're done, init will reap our status. */ sleep(2); printf("Second child, parent pid = %d/n", getppid()); exit(0); } if (waitpid(pid, NULL, 0) != pid) /* wait for first child */ { fprintf(stderr,"Waitpid error!/n"); exit(-1); } /* * We're the parent (the original process); we continue executing, * knowing that we're not the parent of the second child. */ exit(0); }