亚洲av成人无遮挡网站在线观看,少妇性bbb搡bbb爽爽爽,亚洲av日韩精品久久久久久,兔费看少妇性l交大片免费,无码少妇一区二区三区

  免費(fèi)注冊 查看新帖 |

Chinaunix

  平臺 論壇 博客 文庫
123下一頁
最近訪問板塊 發(fā)新帖
查看: 11547 | 回復(fù): 22
打印 上一主題 下一主題

執(zhí)行system后產(chǎn)生defunct,高手進(jìn)來分析下 [復(fù)制鏈接]

論壇徽章:
0
跳轉(zhuǎn)到指定樓層
1 [收藏(0)] [報告]
發(fā)表于 2010-07-22 15:53 |只看該作者 |倒序?yàn)g覽
程序中通過system()調(diào)用另一個可執(zhí)行程序, 如:
if (0 != system("./exe_process args"))
{
     DEBUGLOG("error");
}

但在長期運(yùn)行中經(jīng)常發(fā)現(xiàn)出現(xiàn) exe_process 的defunct進(jìn)程, 看了下system的源碼, 無非就是fork, exec, waitpid

不明白為什么會出現(xiàn)僵尸進(jìn)程

補(bǔ)充: 此程序運(yùn)行時內(nèi)存可能有限, 不知道是否有影響

論壇徽章:
1
天蝎座
日期:2013-10-23 21:11:03
2 [報告]
發(fā)表于 2010-07-22 16:05 |只看該作者
能把源碼貼一下嗎?

論壇徽章:
0
3 [報告]
發(fā)表于 2010-07-22 16:18 |只看該作者
源碼幾乎就是我上面貼的樣子, 就是在一個函數(shù)里調(diào)用system,沒什么特別的

論壇徽章:
84
每日論壇發(fā)貼之星
日期:2015-12-29 06:20:00每日論壇發(fā)貼之星
日期:2016-01-16 06:20:00每周論壇發(fā)貼之星
日期:2016-01-17 22:22:00程序設(shè)計版塊每日發(fā)帖之星
日期:2016-01-20 06:20:00每日論壇發(fā)貼之星
日期:2016-01-20 06:20:00程序設(shè)計版塊每日發(fā)帖之星
日期:2016-01-21 06:20:00每日論壇發(fā)貼之星
日期:2016-01-21 06:20:00程序設(shè)計版塊每日發(fā)帖之星
日期:2016-01-23 06:20:00程序設(shè)計版塊每日發(fā)帖之星
日期:2016-01-31 06:20:00數(shù)據(jù)庫技術(shù)版塊每日發(fā)帖之星
日期:2016-01-16 06:20:00程序設(shè)計版塊每日發(fā)帖之星
日期:2016-01-16 06:20:00程序設(shè)計版塊每日發(fā)帖之星
日期:2016-01-14 06:20:00
4 [報告]
發(fā)表于 2010-07-22 17:52 |只看該作者
僵尸進(jìn)程產(chǎn)生的條件你知道嗎??

論壇徽章:
0
5 [報告]
發(fā)表于 2010-07-22 20:25 |只看該作者
感謝關(guān)注

所謂僵尸進(jìn)程,應(yīng)該是子進(jìn)程退出了, 而父進(jìn)程并沒有處理子進(jìn)程的退出(waitpid或SIGCHLD等), 導(dǎo)致子進(jìn)程的部分資源沒有完全銷毀而產(chǎn)生的吧

理解不對的地方還望指教

我的問題是, system的源碼里是處理了子進(jìn)程的推出的, 不明白什么情況下會產(chǎn)生僵尸

論壇徽章:
0
6 [報告]
發(fā)表于 2010-07-22 22:26 |只看該作者
兩次fork執(zhí)行你的exe

論壇徽章:
0
7 [報告]
發(fā)表于 2010-07-22 22:29 |只看該作者

  1. int startProc(const struct proc_struct* proc)
  2. {
  3.     if(!proc)
  4.         {
  5.                 return 0;
  6.         }
  7.         int pid = fork();
  8.         if(pid == 0)
  9.         {
  10.                 char*szParam[] = {proc->cmdline, proc->param, NULL};
  11.                 pid = fork();
  12.                 if(pid == 0)
  13.                 {
  14.                         execvp(proc->cmdline, szParam);
  15.                         exit(0);
  16.                 }else
  17.                 {
  18.                         exit(0);
  19.                 }
  20.                
  21.         }else
  22.         {
  23.                 wait(NULL);
  24.                 return 1;               
  25.         }       
  26. }
復(fù)制代碼
http://linux.chinaunix.net/bbs/thread-1021030-1-1.html

論壇徽章:
0
8 [報告]
發(fā)表于 2010-07-23 08:54 |只看該作者
感謝樓上解答

其實(shí)我的本意是想知道為什么system會產(chǎn)生僵尸進(jìn)程, 比如有人碰到過、或者能從原理上講明白

當(dāng)然如果解決不了的話可能會考慮改為fork兩次

論壇徽章:
0
9 [報告]
發(fā)表于 2010-07-23 10:11 |只看該作者
本帖最后由 duanjigang 于 2010-07-23 10:21 編輯
感謝樓上解答

其實(shí)我的本意是想知道為什么system會產(chǎn)生僵尸進(jìn)程, 比如有人碰到過、或者能從原理上講明白 ...
morris2600 發(fā)表于 2010-07-23 08:54


首先你可以看下《linux內(nèi)核設(shè)計與實(shí)現(xiàn)》大概前幾章,有一章講這個的。另外,下面
這篇文章說的也很好。
http://hi.baidu.com/kobetec/blog ... dca883e950cdf4.html
怎樣避免產(chǎn)生僵尸進(jìn)程2008-02-20 17:09怎樣避免產(chǎn)生僵尸進(jìn)程
摘錄于: <<Advanced Programming in the UNIX&reg; Environment: Second Edition>> By W. Richard Stevens, Stephen
1.什么是僵尸進(jìn)程?
In UNIX System terminology, a process that has terminated,but whose

parent has not yet waited for it, is called a zombie.

在UNIX 系統(tǒng)中,一個進(jìn)程結(jié)束了,但是他的父進(jìn)程沒有等待(調(diào)用wait / waitpid)他,

那么他將變成一個僵尸進(jìn)程.

但是如果該進(jìn)程的父進(jìn)程已經(jīng)先結(jié)束了,那么該進(jìn)程就不會變成僵尸進(jìn)程,

因?yàn)槊總進(jìn)程結(jié)束的時候,系統(tǒng)都會掃描當(dāng)前系統(tǒng)中所運(yùn)行的所有進(jìn)程,

看有沒有哪個進(jìn)程是剛剛結(jié)束的這個進(jìn)程的子進(jìn)程,如果是的話,就由Init

來接管他,成為他的父進(jìn)程,從而保證每個進(jìn)程都會有一個父進(jìn)程.

而Init進(jìn)程會自動wait 其子進(jìn)程,因此被Init接管的所有進(jìn)程都不會變成僵尸進(jìn)程.

2. 僵尸進(jìn)程的危害
由于子進(jìn)程的結(jié)束和父進(jìn)程的運(yùn)行是一個異步過程,即父進(jìn)程永遠(yuǎn)無法預(yù)測子進(jìn)程

到底什么時候結(jié)束. 那么不會因?yàn)楦高M(jìn)程太忙來不及waid子進(jìn)程,或者說不知道

子進(jìn)程什么時候結(jié)束,而丟失子進(jìn)程結(jié)束時的狀態(tài)信息呢?

不會.因?yàn)閁NIX提供了一種機(jī)制可以保證 只要父進(jìn)程想知道子進(jìn)程結(jié)束時的狀態(tài)信息,

就可以得到. 這種機(jī)制就是:

在每個進(jìn)程退出的時候,內(nèi)核釋放該進(jìn)程所有的資源,包括打開的文件,占用的內(nèi)存等.

但是仍然為其保留一定的信息(包括進(jìn)程號the process ID,退出狀態(tài)the termination

status of the process,運(yùn)行時間the amount of CPU time taken by the process等),

直到父進(jìn)程通過wait / waitpid來取時才釋放.

但這樣就導(dǎo)致了問題,如果你進(jìn)程不調(diào)用wait / waitpid的話, 那么保留的那段信息就不會

釋放,其進(jìn)程號就會一定被占用,但是系統(tǒng)所能使用的進(jìn)程號是有限的,如果大量的產(chǎn)生

僵死進(jìn)程,將因?yàn)闆]有可用的進(jìn)程號而導(dǎo)致系統(tǒng)不能產(chǎn)生新的進(jìn)程.

此即為僵尸進(jìn)程的危害,應(yīng)當(dāng)避免.

3.僵尸進(jìn)程的避免
1、父進(jìn)程通過wait和waitpid等函數(shù)等待子進(jìn)程結(jié)束,這會導(dǎo)致父進(jìn)程掛起

2. 如果父進(jìn)程很忙,那么可以用signal函數(shù)為SIGCHLD安裝handler,因?yàn)樽舆M(jìn)程結(jié)束后,

父進(jìn)程會收到該信號,可以在handler中調(diào)用wait回收


3. 如果父進(jìn)程不關(guān)心子進(jìn)程什么時候結(jié)束,那么可以用signal(SIGCHLD, SIG_IGN)

通知內(nèi)核,自己對子進(jìn)程的結(jié)束不感興趣,那么子進(jìn)程結(jié)束后,內(nèi)核會回收,

并不再給父進(jìn)程發(fā)送信號

4. 還有一些技巧,就是fork兩次,父進(jìn)程fork一個子進(jìn)程,然后繼續(xù)工作,子進(jìn)程fork一

個孫進(jìn)程后退出,那么孫進(jìn)程被init接管,孫進(jìn)程結(jié)束后,init會回收。不過子進(jìn)程的回收

還要自己做。 下面就是Stevens給的采用兩次folk避免僵尸進(jìn)程的示例.

Example
Recall our discussion in Section 8.5 about zombie processes. If we want to write a process so that it forks a child but we don't want to wait for the child to complete and we don't want the child to become a zombie until we terminate, the trick is to call fork twice. The program in Figure 8.8 does this.

We call sleep in the second child to ensure that the first child terminates before printing the parent process ID. After a fork, either the parent or the child can continue executing; we never know which will resume execution first. If we didn't put the second child to sleep, and if it resumed execution after the fork before its parent, the parent process ID that it printed would be that of its parent, not process ID 1.

  1. #include "apue.h"
  2. #include <sys/wait.h>

  3. int
  4. main(void)
  5. ...{
  6.      pid_t    pid;

  7.     if ((pid = fork()) < 0) ...{
  8.          err_sys("fork error");
  9.      } else if (pid == 0) ...{     /**//* first child */
  10.         if ((pid = fork()) < 0)
  11.              err_sys("fork error");
  12.         else if (pid > 0)
  13.              exit(0);    /**//* parent from second fork == first child */
  14.         /**//*
  15.           * We're the second child; our parent becomes init as soon
  16.           * as our real parent calls exit() in the statement above.
  17.           * Here's where we'd continue executing, knowing that when
  18.           * we're done, init will reap our status.
  19.          */
  20.          sleep(2);
  21.          printf("second child, parent pid = %d ", getppid());
  22.          exit(0);
  23.      }
  24.    
  25.     if (waitpid(pid, NULL, 0) != pid)  /**//* wait for first child */
  26.          err_sys("waitpid error");

  27.     /**//*
  28.       * We're the parent (the original process); we continue executing,
  29.       * knowing that we're not the parent of the second child.
  30.      */
  31.      exit(0);
  32. }

復(fù)制代碼

論壇徽章:
0
10 [報告]
發(fā)表于 2010-07-23 10:13 |只看該作者
本帖最后由 duanjigang 于 2010-07-23 10:16 編輯

根據(jù)理論我們做個測試的例子。
子進(jìn)程要執(zhí)行的程序test_prog

  1. //test.c
  2. #include <stdio.h>
  3. int main()
  4. {
  5.         int i = 0;
  6.         for (i = 0 ; i < 10; i++)
  7.         {
  8.                 printf ("child time %d\n", i+1);
  9.                 sleep (1);
  10.         }
  11.         return 0;
  12. }
復(fù)制代碼
父進(jìn)程father的代碼father.c

  1. #include <stdio.h>
  2. #include <unistd.h>
  3. #include <sys/types.h>
  4. #include <sys/wait.h>
  5. int main()
  6. {
  7.         int pid = fork ();
  8.         if (pid == 0)
  9.         {
  10.                 system ("./test_prog");
  11.                 _exit (0);
  12.         }else
  13.         {
  14.                 int i = 0;
  15.                 /*
  16.                                 int status = 0;
  17.                 while (!waitpid(pid, &status, WNOHANG))
  18.                 {
  19.                         printf ("father waiting%d\n", ++i);
  20.                         sleep (1);
  21.                 }*/
  22.                 while (1)
  23.                 {
  24.                         printf ("father waiting over%d\n", ++i);
  25.                         sleep (1);
  26.                 }
  27.                 return 0;
  28.         }

  29. }
復(fù)制代碼
執(zhí)行./father,當(dāng)子進(jìn)程退出后,由于父進(jìn)程沒有對它的退出進(jìn)行關(guān)注,會出現(xiàn)僵尸進(jìn)程

  1. 20786 pts/0    00:00:00 father
  2. 20787 pts/0    00:00:00 father <defunct>
復(fù)制代碼
您需要登錄后才可以回帖 登錄 | 注冊

本版積分規(guī)則 發(fā)表回復(fù)

  

北京盛拓優(yōu)訊信息技術(shù)有限公司. 版權(quán)所有 京ICP備16024965號-6 北京市公安局海淀分局網(wǎng)監(jiān)中心備案編號:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年舉報專區(qū)
中國互聯(lián)網(wǎng)協(xié)會會員  聯(lián)系我們:huangweiwei@itpub.net
感謝所有關(guān)心和支持過ChinaUnix的朋友們 轉(zhuǎn)載本站內(nèi)容請注明原作者名及出處

清除 Cookies - ChinaUnix - Archiver - WAP - TOP