国产成人精品三级麻豆,色综合天天综合高清网,亚洲精品夜夜夜,国产成人综合在线女婷五月99播放,色婷婷色综合激情国产日韩

當(dāng)前位置:首頁(yè) > 嵌入式培訓(xùn) > 嵌入式學(xué)習(xí) > 講師博文 > 孤兒進(jìn)程和僵尸進(jìn)程

孤兒進(jìn)程和僵尸進(jìn)程 時(shí)間:2018-08-15      來(lái)源:未知

前段時(shí)間,由于研究經(jīng)典面試題,把孤兒進(jìn)程和僵尸進(jìn)程也總結(jié)了一下。

我們有這樣一個(gè)問(wèn)題:孤兒進(jìn)程和僵尸進(jìn)程,怎么產(chǎn)生的?有什么危害?怎么去預(yù)防?

下面是針對(duì)此問(wèn)題的總結(jié)與概括。

一.產(chǎn)生的原因

1) 一般進(jìn)程

正常情況下:子進(jìn)程由父進(jìn)程創(chuàng)建,子進(jìn)程再創(chuàng)建新的進(jìn)程。父子進(jìn)程是一個(gè)異步過(guò)程,父進(jìn)程永遠(yuǎn)無(wú)法預(yù)測(cè)子進(jìn)程的結(jié)束,所以,當(dāng)子進(jìn)程結(jié)束后,它的父進(jìn)程會(huì)調(diào)用wait()或waitpid()取得子進(jìn)程的終止?fàn)顟B(tài),回收掉子進(jìn)程的資源。

2)孤兒進(jìn)程

孤兒進(jìn)程:父進(jìn)程結(jié)束了,而它的一個(gè)或多個(gè)子進(jìn)程還在運(yùn)行,那么這些子進(jìn)程就成為孤兒進(jìn)程(father died)。子進(jìn)程的資源由init進(jìn)程(進(jìn)程號(hào)PID = 1)回收。

3)僵尸進(jìn)程

僵尸進(jìn)程:子進(jìn)程退出了,但是父進(jìn)程沒(méi)有用wait或waitpid去獲取子進(jìn)程的狀態(tài)信息,那么子進(jìn)程的進(jìn)程描述符仍然保存在系統(tǒng)中,這種進(jìn)程稱為僵死進(jìn)程。

二.問(wèn)題危害

注意:unix提供了一種機(jī)制保證父進(jìn)程知道子進(jìn)程結(jié)束時(shí)的狀態(tài)信息。

這種機(jī)制是:在每個(gè)進(jìn)程退出的時(shí)候,內(nèi)核會(huì)釋放所有的資源,包括打開(kāi)的文件,占用的內(nèi)存等。但是仍保留一部分信息(進(jìn)程號(hào)PID,退出狀態(tài),運(yùn)行時(shí)間等)。直到父進(jìn)程通過(guò)wait或waitpid來(lái)取時(shí)才釋放。

但是這樣就會(huì)產(chǎn)生問(wèn)題:如果父進(jìn)程不調(diào)用wait或waitpid的話,那么保留的信息就不會(huì)被釋放,其進(jìn)程號(hào)就會(huì)被一直占用,但是系統(tǒng)所能使用的進(jìn)程號(hào)是有限的,如果大量產(chǎn)生僵死進(jìn)程,將因沒(méi)有可用的進(jìn)程號(hào)而導(dǎo)致系統(tǒng)無(wú)法產(chǎn)生新的進(jìn)程,這就是僵尸進(jìn)程的危害

孤兒進(jìn)程是沒(méi)有父進(jìn)程的進(jìn)程,它由init進(jìn)程循環(huán)的wait()回收資源,init進(jìn)程充當(dāng)父進(jìn)程。因此孤兒進(jìn)程并沒(méi)有什么危害。

補(bǔ)充:任何一個(gè)子進(jìn)程(init除外)在exit()之后,并非馬上就消失掉,而是留下一個(gè)稱為僵尸進(jìn)程的數(shù)據(jù)結(jié)構(gòu),等待父進(jìn)程去處理。如果父進(jìn)程在子進(jìn)程exit()之后,沒(méi)有及時(shí)處理,出現(xiàn)僵尸進(jìn)程,并可以用ps命令去查看,它的狀態(tài)是“Z”。

三.解決方案

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

嚴(yán)格的說(shuō),僵尸進(jìn)程并不是問(wèn)題的根源,罪魁禍?zhǔn)资钱a(chǎn)生大量僵死進(jìn)程的父進(jìn)程。因此,我們可以直接除掉元兇,通過(guò)kill發(fā)送SIGTERM或者SIGKILL信號(hào)。元兇死后,僵尸進(jìn)程進(jìn)程變成孤兒進(jìn)程,由init充當(dāng)父進(jìn)程,并回收資源。

或者運(yùn)行:kill -9 父進(jìn)程的pid值、

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

父進(jìn)程通過(guò)wait或waitpid等函數(shù)去等待子進(jìn)程結(jié)束,但是不好,會(huì)導(dǎo)致父進(jìn)程一直等待被掛起,相當(dāng)于一個(gè)進(jìn)程在干活,沒(méi)有起到多進(jìn)程的作用。

3)通過(guò)信號(hào)機(jī)制,在處理函數(shù)中調(diào)用wait,回收資源

通過(guò)信號(hào)機(jī)制,子進(jìn)程退出時(shí)向父進(jìn)程發(fā)送SIGCHLD信號(hào),父進(jìn)程調(diào)用signal(SIGCHLD,sig_child)去處理SIGCHLD信號(hào),在信號(hào)處理函數(shù)sig_child()中調(diào)用wait進(jìn)行處理僵尸進(jìn)程。什么時(shí)候得到子進(jìn)程信號(hào),什么時(shí)候進(jìn)行信號(hào)處理,父進(jìn)程可以繼續(xù)干其他活,不用去阻塞等待。

例子1:

#include

#include

#include

#include

#include

static void sig_child(int signo);

int main()

{

pid_t pid;

//創(chuàng)建捕捉子進(jìn)程退出信號(hào)

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

//等待子進(jìn)程先退出

sleep(2);

//輸出進(jìn)程信息

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;

//處理僵尸進(jìn)程

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

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

}

4)fork兩次

fork兩次,父進(jìn)程fork一個(gè)子進(jìn)程,子進(jìn)程在fork出一個(gè)孫子進(jìn)程,然后子進(jìn)程立馬退出,并由父進(jìn)程去wait回收,這個(gè)過(guò)程不需要等待,然后父進(jìn)程可以去干其他的活。孫子進(jìn)程因?yàn)樽舆M(jìn)程退出會(huì)成為孤兒進(jìn)程,那它可以由init充當(dāng)父進(jìn)程,并回收。這樣父進(jìn)程和孫子進(jìn)程就可以同時(shí)干活,互不影響,就實(shí)現(xiàn)了多進(jìn)程。

例子2:

#include

#include

#include

#include

int main()

{

pid_t pid;

//創(chuàng)建第一個(gè)子進(jìn)程

pid = fork();

if (pid < 0)

{

perror("fork error:");

exit(1);

}

//第一個(gè)子進(jìn)程

else if (pid == 0)

{

//子進(jìn)程再創(chuàng)建子進(jìn)程

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

pid = fork();

if (pid < 0)

{

perror("fork error:");

exit(1);

}

//第一個(gè)子進(jìn)程退出

else if (pid >0)

{

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

exit(0);

}

//第二個(gè)子進(jìn)程

//睡眠3s保證第一個(gè)子進(jìn)程退出,這樣第二個(gè)子進(jìn)程的父親就是init進(jìn)程里

sleep(3);

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

exit(0);

}

//父進(jìn)程處理第一個(gè)子進(jìn)程退出

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

{

perror("waitepid error:");

exit(1);

}

exit(0);

return 0;

}

四.補(bǔ)充測(cè)試程序

1)孤兒進(jìn)程測(cè)試程序

#include

#include

#include

#include

int main()

{

pid_t pid;

//創(chuàng)建一個(gè)進(jìn)程

pid = fork();

//創(chuàng)建失敗

if (pid < 0)

{

perror("fork error:");

exit(1);

}

//子進(jìn)程

if (pid == 0)

{

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

//輸出進(jìn)程ID和父進(jìn)程ID

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

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

//睡眠5s,保證父進(jìn)程先退出

sleep(5);

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

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

}

//父進(jìn)程

else

{

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

//父進(jìn)程睡眠1s,保證子進(jìn)程輸出進(jìn)程id

sleep(1);

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

}

return 0;

}

2)僵尸進(jìn)程測(cè)試程序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");

//等待子進(jìn)程先退出

sleep(2);

//輸出進(jìn)程信息

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

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

return 0;

}

3)僵尸進(jìn)程測(cè)試程序2

#include

#include

#include

#include

int main()

{

pid_t pid;

//循環(huán)創(chuàng)建子進(jìn)程

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

//子進(jìn)程退出,成為僵尸進(jìn)程

exit(0);

}

else

{

//父進(jìn)程休眠20s繼續(xù)創(chuàng)建子進(jìn)程

sleep(20);

continue;

}

}

return 0;

}

4)僵尸進(jìn)程測(cè)試程序2--測(cè)試效果

運(yùn)行可執(zhí)行程序顯示:

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

開(kāi)另外一個(gè)終端:

運(yùn)行:

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

顯示:(狀態(tài)Z代表僵尸進(jìn)程)

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

用第一種方法,解決僵尸進(jìn)程,殺死其父進(jìn)程

運(yùn)行:kill -9 3213

注意:僵尸進(jìn)程無(wú)法用kill直接殺死,如kill -9 3214,再用上面命令去查看進(jìn)程狀態(tài),發(fā)現(xiàn)3214進(jìn)程還在。

五. 參考文獻(xiàn)

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

《unix環(huán)境高級(jí)編程》第八章

上一篇:Linux C中對(duì)json格式數(shù)組數(shù)據(jù)的生成與解析

下一篇:傳感器尺寸

熱點(diǎn)文章推薦
華清學(xué)員就業(yè)榜單
高薪學(xué)員經(jīng)驗(yàn)分享
熱點(diǎn)新聞推薦
前臺(tái)專線:010-82525158 企業(yè)培訓(xùn)洽談專線:010-82525379 院校合作洽談專線:010-82525379 Copyright © 2004-2022 北京華清遠(yuǎn)見(jiàn)科技集團(tuán)有限公司 版權(quán)所有 ,京ICP備16055225號(hào)-5,京公海網(wǎng)安備11010802025203號(hào)

回到頂部