物聯網教程Linux系統程式設計——特殊程式之殭屍程式
Linux系統程式設計——特殊程式之殭屍程式
殭屍程式(Zombie Process)
程式已執行結束,但程式的佔用的資源未被回收,這樣的程式稱為殭屍程式。
在每個程式退出的時候,核心釋放該程式所有的資源、包括開啟的檔案、佔用的記憶體等。但是仍然為其保留一定的資訊,這些資訊主要主要指程式控制塊的資訊(包括程式號、退出狀態、執行時間等)。直到父程式透過wait()或waitpid()來獲取其狀態並釋放(具體用法,請看《等待程式結束》)。這樣就會導致一個問題,如果程式不呼叫wait()或waitpid()的話,那麼保留的那段資訊就不會釋放,其程式號就會一直被佔用,但是系統所能使用的程式號是有限的,如果大量的產生僵死程式,將因為沒有可用的程式號而導致系統不能產生新的程式.此即為殭屍程式的危害,應當避免。
子程式已執行結束,父程式未呼叫wait()或waitpid()函式回收子程式的資源是子程式變為殭屍程式的原因。
殭屍程式測試程式如下:
#include<stdio.h>
#include<unistd.h>
#include<errno.h>
#include<stdlib.h>
int main(int argc,char*argv[])
{
pid_t pid;
pid=fork();//建立程式
if(pid<0){//出錯
perror("fork error:");
exit(1);
}else if(0==pid){//子程式
printf("I am child process.I am exiting.\n");
printf("[son id]:%d\n",getpid());
exit(0);
}else if(pid>0){//父程式
//父程式沒有呼叫wati()或watipid()
sleep(1);//保證子程式先執行
printf("I am father process.I will sleep two seconds\n");
printf("[father id]:%d\n",getpid());
while(1);//不讓父程式退出
}
return 0;
}
如何避免殭屍程式?
1)最簡單的方法,父程式透過wait()和waitpid()等函式等待子程式結束,但是,這會導致父程式掛起。具體用法,請看《程式的控制:結束程式、等待程式結束》。
2)如果父程式要處理的事情很多,不能夠掛起,透過signal()函式人為處理訊號SIGCHLD,只要有子程式退出自動呼叫指定好的回撥函式,因為子程式結束後,父程式會收到該訊號SIGCHLD,可以在其回撥函式里呼叫wait()或waitpid()回收。關於訊號的更詳細用法,請看《訊號中斷處理》。
測試程式碼如下:
#include<stdio.h>
#include<unistd.h>
#include<errno.h>
#include<stdlib.h>
#include<signal.h>
void sig_child(int signo)
{
pid_t pid;
//處理殭屍程式,-1代表等待任意一個子程式,WNOHANG代表不阻塞
while((pid=waitpid(-1,NULL,WNOHANG))>0){
printf("child%d terminated.\n",pid);
}
}
int main()
{
pid_t pid;
//建立捕捉子程式退出訊號
//只要子程式退出,觸發SIGCHLD,自動呼叫sig_child()
signal(SIGCHLD,sig_child);
pid=fork();//建立程式
if(pid<0){//出錯
perror("fork error:");
exit(1);
}else if(pid==0){//子程式
printf("I am child process,pid id%d.I am exiting.\n",getpid());
exit(0);
}else if(pid>0){//父程式
sleep(2);//保證子程式先執行
printf("I am father,i am exited\n\n");
system("ps-ef|grep defunct");//檢視有沒有殭屍程式
}
return 0;
}
執行結果:
3)如果父程式不關心子程式什麼時候結束,那麼可以用signal(SIGCHLD,SIG_IGN)通知核心,自己對子程式的結束不感興趣,父程式忽略此訊號,那麼子程式結束後,核心會回收,並不再給父程式傳送訊號。關於訊號的更詳細用法,請看《訊號中斷處理》。
#include<stdio.h>
#include<unistd.h>
#include<errno.h>
#include<stdlib.h>
#include<signal.h>
int main()
{
pid_t pid;
//忽略子程式退出訊號的訊號
//那麼子程式結束後,核心會回收,並不再給父程式傳送訊號
signal(SIGCHLD,SIG_IGN);
pid=fork();//建立程式
if(pid<0){//出錯
perror("fork error:");
exit(1);
}else if(pid==0){//子程式
printf("I am child process,pid id%d.I am exiting.\n",getpid());
exit(0);
}else if(pid>0){//父程式
sleep(2);//保證子程式先執行
printf("I am father,i am exited\n\n");
system("ps-ef|grep defunct");//檢視有沒有殭屍程式
}
return 0;
}
執行結果:
4)還有一些技巧,就是fork()兩次,父程式fork()一個子程式,然後繼續工作,子程式fork()一個孫程式後退出,那麼孫程式被init接管,孫程式結束後,init(1號程式)會回收。不過子程式的回收還要自己做。《UNIX環境高階程式設計》8.6節說的非常詳細。原理是將子程式成為孤兒程式,從而其的父程式變為init程式(1號程式),透過init程式(1號程式)可以處理殭屍程式。更多詳情,請看《特殊程式之孤兒程式》。
原始碼如下:
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<errno.h>
int main()
{
pid_t pid;
//建立第一個子程式
pid=fork();
if(pid<0){//出錯
perror("fork error:");
exit(1);
}else if(pid==0){//子程式
//子程式再建立子程式
printf("I am the first child process.pid:%d\tppid:%d\n",getpid(),getppid());
pid=fork();
if(pid<0){
perror("fork error:");
exit(1);
}else if(pid==0){//子程式
//睡眠3s保證下面的父程式退出,這樣當前子程式的父親就是init程式
sleep(3);
printf("I am the second child process.pid:%d\tppid:%d\n",getpid(),getppid());
exit(0);
}else if(pid>0){//父程式退出
printf("first procee is exited.\n");
exit(0);
}
}else if(pid>0){//父程式
//父程式處理第一個子程式退出,回收其資源
if(waitpid(pid,NULL,0)!=pid){
perror("waitepid error:");
exit(1);
}
exit(0);
}
return 0;
}
執行結果:
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69914734/viewspace-2655313/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 物聯網教程Linux系統程式設計——特殊程式之守護程式Linux程式設計
- 物聯網學習教程—Linux系統程式設計之程式介紹Linux程式設計
- linux系統程式設計之程式(三):程式複製fork,孤兒程式,殭屍程式Linux程式設計
- 【系統】 殭屍程式
- Linux 系統中殭屍程式Linux
- Linux系統殭屍程式詳解Linux
- Linux系統程式設計——特殊程式之孤兒程式Linux程式設計
- Linux 殭屍程式Linux
- 殭屍程式
- 物聯網學習教程—Linux系統程式設計之多工實現(二)Linux程式設計
- 檢視 Linux 殭屍程式Linux
- Linux殭屍程式處置Linux
- Linux中殭屍程式是什麼意思?怎麼檢視殭屍程式?Linux
- 殭屍程式,孤兒程式
- Linux 效能優化之 CPU 篇 ----- 殭屍程式Linux優化
- Linux 中殭屍程式詳解Linux
- Linux如何殺掉殭屍程式Linux
- 殭屍程式和孤兒程式
- 什麼是殭屍程式,如何找到並殺掉殭屍程式?
- fork和殭屍程式
- 殺死殭屍程式
- 子程式、孤兒程式,殭屍程式, init程式
- Perl程式:殭屍程式和孤兒程式
- linux系統程式設計之程式(一):程式與程式Linux程式設計
- Linux程式管理、程式建立、執行緒實現、殭屍程式Linux執行緒
- Linux系統程式設計之程式介紹Linux程式設計
- hp-unix 殭屍程式導致系統崩潰
- 物聯網裝置殭屍網路趨勢分析
- 超大規模的物聯網殭屍網路:Pink
- 物聯網學習教程Linux系統程式設計之檔案描述符的複製:dup()和dup2()Linux程式設計
- linux系統程式設計影片教程(轉)Linux程式設計
- 殭屍蜜網:首款具備誘捕及反探測能力的物聯網殭屍網路
- Linux系統程式設計(8)—— 程式之程式控制函式forkLinux程式設計函式
- Linux系統程式設計(37)—— socket程式設計之原始套接字Linux程式設計
- 系統中出現大量不可中斷程式(D)和殭屍程式(Z)怎麼辦?
- Linux系統程式設計之匿名管道Linux程式設計
- linux系統程式設計之程式(七):system()函式使用Linux程式設計函式
- Go Exec 殭屍與孤兒程式Go