色yeye在线视频观看_亚洲人亚洲精品成人网站_一级毛片免费播放_91精品一区二区中文字幕_一区二区三区日本视频_成人性生交大免费看

當前位置:首頁 > 嵌入式培訓 > 嵌入式學習 > 講師博文 > 孤兒進程和僵尸進程

孤兒進程和僵尸進程 時間:2018-08-15      來源:未知

前段時間,由于研究經典面試題,把孤兒進程和僵尸進程也總結了一下。

我們有這樣一個問題:孤兒進程和僵尸進程,怎么產生的?有什么危害?怎么去預防?

下面是針對此問題的總結與概括。

一.產生的原因

1) 一般進程

正常情況下:子進程由父進程創建,子進程再創建新的進程。父子進程是一個異步過程,父進程永遠無法預測子進程的結束,所以,當子進程結束后,它的父進程會調用wait()或waitpid()取得子進程的終止狀態,回收掉子進程的資源。

2)孤兒進程

孤兒進程:父進程結束了,而它的一個或多個子進程還在運行,那么這些子進程就成為孤兒進程(father died)。子進程的資源由init進程(進程號PID = 1)回收。

3)僵尸進程

僵尸進程:子進程退出了,但是父進程沒有用wait或waitpid去獲取子進程的狀態信息,那么子進程的進程描述符仍然保存在系統中,這種進程稱為僵死進程。

二.問題危害

注意:unix提供了一種機制保證父進程知道子進程結束時的狀態信息。

這種機制是:在每個進程退出的時候,內核會釋放所有的資源,包括打開的文件,占用的內存等。但是仍保留一部分信息(進程號PID,退出狀態,運行時間等)。直到父進程通過wait或waitpid來取時才釋放。

但是這樣就會產生問題:如果父進程不調用wait或waitpid的話,那么保留的信息就不會被釋放,其進程號就會被一直占用,但是系統所能使用的進程號是有限的,如果大量產生僵死進程,將因沒有可用的進程號而導致系統無法產生新的進程,這就是僵尸進程的危害

孤兒進程是沒有父進程的進程,它由init進程循環的wait()回收資源,init進程充當父進程。因此孤兒進程并沒有什么危害。

補充:任何一個子進程(init除外)在exit()之后,并非馬上就消失掉,而是留下一個稱為僵尸進程的數據結構,等待父進程去處理。如果父進程在子進程exit()之后,沒有及時處理,出現僵尸進程,并可以用ps命令去查看,它的狀態是“Z”。

三.解決方案

1)kill殺死元兇父進程(一般不用)

嚴格的說,僵尸進程并不是問題的根源,罪魁禍首是產生大量僵死進程的父進程。因此,我們可以直接除掉元兇,通過kill發送SIGTERM或者SIGKILL信號。元兇死后,僵尸進程進程變成孤兒進程,由init充當父進程,并回收資源。

或者運行:kill -9 父進程的pid值、

2)父進程用wait或waitpid去回收資源(方案不好)

父進程通過wait或waitpid等函數去等待子進程結束,但是不好,會導致父進程一直等待被掛起,相當于一個進程在干活,沒有起到多進程的作用。

3)通過信號機制,在處理函數中調用wait,回收資源

通過信號機制,子進程退出時向父進程發送SIGCHLD信號,父進程調用signal(SIGCHLD,sig_child)去處理SIGCHLD信號,在信號處理函數sig_child()中調用wait進行處理僵尸進程。什么時候得到子進程信號,什么時候進行信號處理,父進程可以繼續干其他活,不用去阻塞等待。

例子1:

#include

#include

#include

#include

#include

static void sig_child(int signo);

int main()

{

pid_t pid;

//創建捕捉子進程退出信號

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);

}

printf("I am father process.I will sleep two seconds\n");

//等待子進程先退出

sleep(2);

//輸出進程信息

system("ps -o pid,ppid,state,tty,command");

printf("father process is exiting.\n");

return 0;

}

static void sig_child(int signo)

{

pid_t pid;

int stat;

//處理僵尸進程

while ((pid = waitpid(-1, &stat, WNOHANG)) >0)

printf("child %d terminated.\n", pid);

}

4)fork兩次

fork兩次,父進程fork一個子進程,子進程在fork出一個孫子進程,然后子進程立馬退出,并由父進程去wait回收,這個過程不需要等待,然后父進程可以去干其他的活。孫子進程因為子進程退出會成為孤兒進程,那它可以由init充當父進程,并回收。這樣父進程和孫子進程就可以同時干活,互不影響,就實現了多進程。

例子2:

#include

#include

#include

#include

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)

{

printf("first procee is exited.\n");

exit(0);

}

//第二個子進程

//睡眠3s保證第一個子進程退出,這樣第二個子進程的父親就是init進程里

sleep(3);

printf("I am the second child process.pid: %d\tppid:%d\n",getpid(),getppid());

exit(0);

}

//父進程處理第一個子進程退出

if (waitpid(pid, NULL, 0) != pid)

{

perror("waitepid error:");

exit(1);

}

exit(0);

return 0;

}

四.補充測試程序

1)孤兒進程測試程序

#include

#include

#include

#include

int main()

{

pid_t pid;

//創建一個進程

pid = fork();

//創建失敗

if (pid < 0)

{

perror("fork error:");

exit(1);

}

//子進程

if (pid == 0)

{

printf("I am the child process.\n");

//輸出進程ID和父進程ID

printf("pid: %d\tppid:%d\n",getpid(),getppid());

printf("I will sleep five seconds.\n");

//睡眠5s,保證父進程先退出

sleep(5);

printf("pid: %d\tppid:%d\n",getpid(),getppid());

printf("child process is exited.\n");

}

//父進程

else

{

printf("I am father process.\n");

//父進程睡眠1s,保證子進程輸出進程id

sleep(1);

printf("father process is exited.\n");

}

return 0;

}

2)僵尸進程測試程序1

int main()

{

pid_t pid;

pid = fork();

if (pid < 0)

{

perror("fork error:");

exit(1);

}

else if (pid == 0)

{

printf("I am child process.I am exiting.\n");

exit(0);

}

printf("I am father process.I will sleep two seconds\n");

//等待子進程先退出

sleep(2);

//輸出進程信息

system("ps -o pid,ppid,state,command");

printf("father process is exiting.\n");

return 0;

}

3)僵尸進程測試程序2

#include

#include

#include

#include

int main()

{

pid_t pid;

//循環創建子進程

while(1)

{

pid = fork();

if (pid < 0)

{

perror("fork error:");

exit(1);

}

else if (pid == 0)

{

printf("I am a child process.\nI am exiting.\n");

//子進程退出,成為僵尸進程

exit(0);

}

else

{

//父進程休眠20s繼續創建子進程

sleep(20);

continue;

}

}

return 0;

}

4)僵尸進程測試程序2--測試效果

運行可執行程序顯示:

I am a child process.

I am exiting.

I am a child process.

I am exiting.

I am a child process.

I am exiting.

I am a child process.

I am exiting.

I am a child process.

I am exiting.

I am a child process.

I am exiting.

Killed

開另外一個終端:

運行:

ps -a -o pid,ppid,state,cmd

顯示:(狀態Z代表僵尸進程)

S PID PPID CMD

S 3213 2529 ./pid1

Z 3214 3213 [pid1]

Z 3215 3213 [pid1]

Z 3219 3213 [pid1]

Z 3220 3213 [pid1]

Z 3221 3213 [pid1]

R 3223 3104 ps -a -o state,pid,ppid,cmd

用第一種方法,解決僵尸進程,殺死其父進程

運行:kill -9 3213

注意:僵尸進程無法用kill直接殺死,如kill -9 3214,再用上面命令去查看進程狀態,發現3214進程還在。

五. 參考文獻

//www.cnblogs.com/Anker/p/3271773.html

《unix環境高級編程》第八章

上一篇:Linux C中對json格式數組數據的生成與解析

下一篇:傳感器尺寸

熱點文章推薦
華清學員就業榜單
高薪學員經驗分享
熱點新聞推薦
前臺專線:010-82525158 企業培訓洽談專線:010-82525379 院校合作洽談專線:010-82525379 Copyright © 2004-2022 北京華清遠見科技集團有限公司 版權所有 ,京ICP備16055225號-5京公海網安備11010802025203號

回到頂部

主站蜘蛛池模板: kendralust性潮喷hdbrazzers | 中文一区一区三区免费在线观看 | 国产欧美精品一区二区三区-老狼 | 中文字幕二三区 | 国产精品高潮呻吟AV久久无吗 | 欧美人与ZOXXXX视频 | 无码人妻精品一区二区三区蜜桃 | 日本aⅴ亚洲精品中文乱码 美女胸18大禁视频网站 | 国产成人精品一区二区视频 | 亚洲欧洲日产国码中文字幕 | 日本黄色影片在线观看 | 中文资源在线观看 | 亚洲AV无码AV男人的天堂 | 欧美精品狠狠色丁香婷婷 | av免费一区二区 | 曰本大码熟中文字幕 | 最新影视在线观看 | 国产亚洲精品无码成人 | 中文字幕无码日韩专区免费 | 老头巨大挺进莹莹的体内免费视频 | 欧洲精品色在线观看 | 被夫上司強暴人妻中文字幕 | 又黄又粗暴的120秒免费GIF视频 | 亚洲AV无码久久久久网站蜜桃 | 午夜性色福利在线视频18观看 | 永久免费人禽AV在线观看 | 亚洲不乱码卡一卡二卡4卡5 | 在线中文字幕乱码英文字幕正常 | 久久精品青草社区 | 在线不卡日本 | 佐山爱一区二区中文字幕 | 欧美videos另类极品 | 日本五月天婷久久网站 | 美女18免费 | 久久香蕉国产线看观看猫咪AV | 高清国产精品人妻一区二区 | 一二三四在线观看免费高清中文在线观看 | 无码专区一ⅴa亚洲v专区在线 | 中文字幕国产一区二区三区 | 国产嫩草在线 | "欧美 日韩 国产精品免费观看" |