色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格式數組數據的生成與解析

下一篇:傳感器尺寸

华清图书馆

0元电子书,限时免费申领

10本华清图书PDF版

扫码关注华清远见公众号
自动回复“2”,即可申领!
熱點文章推薦
華清學員就業榜單
高薪學員經驗分享
熱點新聞推薦
前臺專線:010-82525158 企業培訓洽談專線:010-82525379 院校合作洽談專線:010-82525379 Copyright © 2004-2022 北京華清遠見科技集團有限公司 版權所有 ,京ICP備16055225號-5京公海網安備11010802025203號

回到頂部

主站蜘蛛池模板: 中文字幕熟女人妻伦伦在线 | 久久人人爽人人人澡A片 | 日韩一区二区三区无码A片 字幕网91 | 亚洲日韩乱码中文字幕 | 日韩性公交车上xxhd | 中文无遮挡h肉视频在线观看 | 野花香日本大全免费观看 | 欧美小泬xxxbbb视频 | 国产av无码专区亚洲版综合 | 欧美日韩视频无码一区二区三 | 成年男女免费视频网站很黄的 | 日本丰满熟妇无码惨叫 | 少妇大叫又粗又大太爽A片 天堂网资源中文最新版 | "久久国产精品 国产精品" | 亚洲爆乳精品无码一区二区三区 | 久久久久亚洲AV成人无码网站 | 日本边添边摸边做边爱 | 中文字幕第一区二区 | 极品少妇ⅩXXXⅩ护士 | 国产乱子伦一区二区三区四区五区 | 久久久久无码精品国产情侣 | 欧美 日韩 高清 | 亚洲经典千人经典日产 | 亚洲AV无码一区二区二三区入口 | 无遮挡啪啪摇乳动态图GIF | 老熟女高潮一区二区三区 | 国产一二三四2021精字窝 | 四虎成人精品永久网站 | 亚洲色大18成人网站WWW在线播放 | 激情影院内射美女 | 四虎永久在线精品免费无码 | 三年片在线观看免费观看大全动漫 | 亚洲有无码av在线播放 | 麻豆传媒在线免费 | 五月天综合网缴情五月中文 | 亚洲国产理论片在线播放 | 极品美女扒开粉嫩小泬18P | 快色视频网站 | 乱码精品一卡二卡无卡 | 中文字幕精品AV乱码在线 | 金瓶梅在线观看AV片 |