• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            posts - 297,  comments - 15,  trackbacks - 0
            在fork()/execve()過程中,假設(shè)子進(jìn)程結(jié)束時(shí)父進(jìn)程仍存在,而父進(jìn)程fork()之前既沒安裝SIGCHLD信號處理函數(shù)調(diào)用 waitpid()等待子進(jìn)程結(jié)束,又沒有顯式忽略該信號,則子進(jìn)程成為僵尸進(jìn)程,無法正常結(jié)束,此時(shí)即使是root身份kill-9也不能殺死僵尸進(jìn) 程。補(bǔ)救辦法是殺死僵尸進(jìn)程的父進(jìn)程(僵尸進(jìn)程的父進(jìn)程必然存在),僵尸進(jìn)程成為"孤兒進(jìn)程",過繼給1號進(jìn)程init,init始終會負(fù)責(zé)清理僵尸進(jìn) 程。

              僵尸進(jìn)程是指的父進(jìn)程已經(jīng)退出,而該進(jìn)程dead之后沒有進(jìn)程接受,就成為僵尸進(jìn)程.(zombie)進(jìn)程

              怎樣產(chǎn)生僵尸進(jìn)程的:

              一個(gè)進(jìn)程在調(diào)用exit命令結(jié)束自己的生命的時(shí)候,其實(shí)它并沒有真正的被銷毀,而是留下一個(gè)稱為僵尸進(jìn)程(Zombie)的數(shù)據(jù)結(jié)構(gòu)(系統(tǒng)調(diào)用 exit,它的作用是使進(jìn)程退出,但也僅僅限于將一個(gè)正常的進(jìn)程變成一個(gè)僵尸進(jìn)程,并不能將其完全銷毀)。在Linux進(jìn)程的狀態(tài)中,僵尸進(jìn)程是非常特殊的一種,它已經(jīng)放棄了幾乎所有內(nèi)存空間,沒有任何可執(zhí)行代碼,也不能被調(diào)度,僅僅在進(jìn)程列表中保留一個(gè)位置,記載該進(jìn)程的退出狀態(tài)等信息供其他進(jìn)程收集,除此之外,僵尸進(jìn)程不再占有任何內(nèi)存空間。它需要它的父進(jìn)程來為它收尸,如果他的父進(jìn)程沒安裝SIGCHLD信號處理函數(shù)調(diào)用wait或waitpid()等待子進(jìn)程結(jié)束,又沒有顯式忽略該信號,那么它就一直保持僵尸狀態(tài),如果這時(shí)父進(jìn)程結(jié)束了,那么init進(jìn)程自動會接手這個(gè)子進(jìn)程,為它收尸,它還是能被清除的。但是如果如果父進(jìn)程是一個(gè)循環(huán),不會結(jié)束,那么子進(jìn)程就會一直保持僵尸狀態(tài),這就是為什么系統(tǒng)中有時(shí)會有很多的僵尸進(jìn)程。

              Linux系統(tǒng)對運(yùn)行的進(jìn)程數(shù)量有限制,如果產(chǎn)生過多的僵尸進(jìn)程占用了可用的進(jìn)程號,將會導(dǎo)致新的進(jìn)程無法生成。這就是僵尸進(jìn)程對系統(tǒng)的最大危害。

              僵尸進(jìn)程實(shí)例:

              /*-----zombie1.c-----*/

              #include "sys/types.h"

              #include "sys/wait.h"

              #include "stdio.h"

              #include "unistd.h"

              int main(int argc, char* argv[])

              {

                      while(1)

                      {

                             pid_t chi = fork();

                              if(chi == 0)

                              {

                                      execl("/bin/bash","bash","-c","ls",NULL);

                              }

                              sleep(2);

              }

              會不停地產(chǎn)生僵死進(jìn)程ls;

              /*-----zombie2.c-----*/

              #include <stdio.h>

              #include<sys/types.h>

              main()

              {

                      if(!fork())

                      {

                              printf("child pid=%d\n", getpid());

                              exit(0);

                      }

                      /*wait();*/

                      /*waitpid(-1,NULL,0);*/

                      sleep(60);

                      printf("parent pid=%d \n", getpid());

                      exit(0);

              }

              60s內(nèi)會不斷產(chǎn)生僵尸進(jìn)程,直到父進(jìn)程exit(0);

              如果在調(diào)用wait/waitpid來為子進(jìn)程收尸,就不會產(chǎn)生僵尸進(jìn)程了。

              PS:運(yùn)行例子,先gcc zombie1.c -o zombie編譯,然后運(yùn)行zombie;

              然后可以可用ps -ef來查看是否產(chǎn)生了僵尸進(jìn)程。

              怎么查看僵尸進(jìn)程:

              利用命令ps,可以看到有標(biāo)記為Z的進(jìn)程就是僵尸進(jìn)程。

              怎樣來清除僵尸進(jìn)程:

              1.改寫父進(jìn)程,在子進(jìn)程死后要為它收尸。具體做法是接管SIGCHLD信號。子進(jìn)程死后,會發(fā)送SIGCHLD信號給父進(jìn)程,父進(jìn)程收到此信 號后,執(zhí)行 waitpid()函數(shù)為子進(jìn)程收尸。這是基于這樣的原理:就算父進(jìn)程沒有調(diào)用wait,內(nèi)核也會向它發(fā)送SIGCHLD消息,盡管對的默認(rèn)處理是忽略, 如果想響應(yīng)這個(gè)消息,可以設(shè)置一個(gè)處理函數(shù)。

            2.把父進(jìn)程殺掉。父進(jìn)程死后,僵尸進(jìn)程成為"孤兒進(jìn)程",過繼給1號進(jìn)程init,init始終會負(fù)責(zé)清理僵尸進(jìn)程.它產(chǎn)生的所有僵尸進(jìn)程也跟著消失
            在Linux中可以用

              ps auwx

              發(fā)現(xiàn)僵尸進(jìn)程

              a all w/ tty, including other users 所有窗口和終端,包括其他用戶的進(jìn)程

              u user-oriented 面向用戶(用戶友好)

              -w,w wide output 寬格式輸出

              x processes w/o controlling ttys

              在僵尸進(jìn)程后面 會標(biāo)注

              ps axf

              看進(jìn)程樹,以樹形方式現(xiàn)實(shí)進(jìn)程列表

              ps axm

              會把線程列出來,在linux下進(jìn)程和線程是統(tǒng)一的,是輕量級進(jìn)程的兩種方式。

              ps axu

              顯示進(jìn)程的詳細(xì)狀態(tài)

              killall

              kill -15

              kill -9

              一般都不能殺掉 defunct進(jìn)程

              用了kill -15,kill -9以后 之后反而會多出更多的僵尸進(jìn)程

              kill -kill pid

              fuser -k pid

              可以考慮殺死他的parent process,

              kill -9 他的parent process

              =========================================== 一個(gè)已經(jīng)終止,但是其父進(jìn)程尚未對其進(jìn)行善后處理(獲取終止子進(jìn)程的有關(guān)信息、釋放它仍占用的資源)的進(jìn)程被稱為僵死進(jìn)程(Zombie Process)。

              避免zombie的方法:

              1)在SVR4中,如果調(diào)用signal或sigset將SIGCHLD的配置設(shè)置為忽略,則不會產(chǎn)生僵死子進(jìn)程。另外,使用SVR4版的 sigaction,則可設(shè)置SA_NOCLDWAIT標(biāo)志以避免子進(jìn)程僵死。

              Linux中也可使用這個(gè),在一個(gè)程序的開始調(diào)用這個(gè)函數(shù)

              signal(SIGCHLD,SIG_IGN);

              2)調(diào)用fork兩次。程序8 - 5 實(shí)現(xiàn)了這一點(diǎn)。

              3)用waitpid等待子進(jìn)程返回.

              ===========================================

              zombie進(jìn)程是僵死進(jìn)程。防止它的辦法,一是用wait,waitpid之類的函數(shù)獲得進(jìn)程的終止?fàn)顟B(tài),以釋放資源。另一個(gè)是fork兩次

              ===========================================

              defunct進(jìn)程只是在process table里還有一個(gè)記錄,其他的資源沒有占用,除非你的系統(tǒng)的process個(gè)數(shù)的限制已經(jīng)快超過了,zombie進(jìn)程不會有更多的壞處。

              可能唯一的方法就是reboot系統(tǒng)可以消除zombie進(jìn)程。

              ===========================================

              任何程序都有僵尸狀態(tài),它占用一點(diǎn)內(nèi)存資源(也就是進(jìn)程表里還有一個(gè)記錄),僅僅是表象而已不必害怕。如果程序有問題有機(jī)會遇見,解決大批量僵尸簡單有效的辦法是重起。kill是無任何效果的

              fork與zombie/defunct"

              在Unix下的一些進(jìn)程的運(yùn)作方式。當(dāng)一個(gè)進(jìn)程死亡時(shí),它并不是完全的消失了。進(jìn)程終止,它不再運(yùn)行,但是還有一些殘留的小東西等待父進(jìn)程收 回。這些殘留的東西包括子進(jìn)程的返回值和其他的一些東西。當(dāng)父進(jìn)程 fork()一個(gè)子進(jìn)程后,它必須用 wait() 或者 waitpid() 等待子進(jìn)程退出。正是這個(gè) wait() 動作來讓子進(jìn)程的殘留物消失。

              自然的,在上述規(guī)則之外有個(gè)例外:父進(jìn)程可以忽略 SIGCLD 軟中斷而不必要 wait()。可以這樣做到(在支持它的系統(tǒng)上,比如Linux):

              main()

              {

              signal(SIGCLD, SIG_IGN); /* now I don't have to wait()! */

            fork();

              fork();

              fork(); /* Rabbits, rabbits, rabbits! */

              }

              現(xiàn)在,子進(jìn)程死亡時(shí)父進(jìn)程沒有 wait(),通常用 ps 可以看到它被顯示為“”。它將永遠(yuǎn)保持這樣 直到 父進(jìn)程 wait(),或者按以下方法處理。

              這里是你必須知道的另一個(gè)規(guī)則:當(dāng)父進(jìn)程在它wait()子進(jìn)程之前死亡了(假定它沒有忽略 SIGCLD),子進(jìn)程將把 init(pid1)進(jìn)程作為它的父進(jìn)程。如果子進(jìn)程工作得很好并能夠控制,這并不是問題。但如果子進(jìn)程已經(jīng)是defunct,我們就有了一點(diǎn)小麻煩。 看,原先的父進(jìn)程不可能再 wait(),因?yàn)樗呀?jīng)消亡了。這樣,init 怎么知道 wait() 這些zombie 進(jìn)程。

              答案:不可預(yù)料的。在一些系統(tǒng)上,init周期性的破壞掉它所有的defunct進(jìn)程。在另外一些系統(tǒng)中,它干脆拒絕成為任何defunct進(jìn) 程的父進(jìn)程,而是馬上毀滅它們。如果你使用上述系統(tǒng)的一種,可以寫一個(gè)簡單的循環(huán),用屬于init的defunct進(jìn)程填滿進(jìn)程表。這大概不會令你的系統(tǒng) 管理員很高興吧?

              你的任務(wù):確定你的父進(jìn)程不要忽略 SIGCLD,也不要 wait() 它 fork() 的所有進(jìn)程。不過,你也未必 要總是這樣做(比如,你要起一個(gè) daemon 或是別的什么東西),但是你必須小心編程,如果你是一個(gè) fork()的新手。另外,也不要在心理上有任何束縛。

              總結(jié):

              子進(jìn)程成為 defunct 直到父進(jìn)程 wait(),除非父進(jìn)程忽略了 SIGCLD 。

              更進(jìn)一步,父進(jìn)程沒有 wait() 就消亡(仍假設(shè)父進(jìn)程沒有忽略 SIGCLD )的子進(jìn)程(活動的或者 defunct)成為 init 的子進(jìn)程,init 用重手法處理它們。


            from:

            http://linux.chinaitlab.com/administer/818916.html


            posted on 2010-08-26 17:09 chatler 閱讀(672) 評論(0)  編輯 收藏 引用 所屬分類: Linux_Coding
            <2010年1月>
            272829303112
            3456789
            10111213141516
            17181920212223
            24252627282930
            31123456

            常用鏈接

            留言簿(10)

            隨筆分類(307)

            隨筆檔案(297)

            algorithm

            Books_Free_Online

            C++

            database

            Linux

            Linux shell

            linux socket

            misce

            • cloudward
            • 感覺這個(gè)博客還是不錯(cuò),雖然做的東西和我不大相關(guān),覺得看看還是有好處的

            network

            OSS

            • Google Android
            • Android is a software stack for mobile devices that includes an operating system, middleware and key applications. This early look at the Android SDK provides the tools and APIs necessary to begin developing applications on the Android platform using the Java programming language.
            • os161 file list

            overall

            搜索

            •  

            最新評論

            閱讀排行榜

            評論排行榜

            国产精品免费久久久久电影网| 色妞色综合久久夜夜| 国产成人精品久久免费动漫| 97久久精品无码一区二区| 品成人欧美大片久久国产欧美...| 国产精品午夜久久| A级毛片无码久久精品免费 | 国产精品亚洲综合专区片高清久久久 | 久久久久无码专区亚洲av| 一本色综合网久久| 久久免费精品一区二区| 亚洲欧美成人久久综合中文网| 国产精品久久久久久吹潮| 国内精品久久久久久久亚洲| 综合网日日天干夜夜久久| 精品久久久久久久中文字幕| 亚洲av伊人久久综合密臀性色| 久久久久久国产精品美女| 蜜臀av性久久久久蜜臀aⅴ麻豆| 久久久久亚洲AV无码永不| 久久久久无码精品| …久久精品99久久香蕉国产| 怡红院日本一道日本久久| 7777久久久国产精品消防器材| 久久久久人妻精品一区二区三区 | 欧洲精品久久久av无码电影| 久久久无码精品亚洲日韩京东传媒| 久久美女网站免费| 精品精品国产自在久久高清| 亚洲精品乱码久久久久久久久久久久 | 国产aⅴ激情无码久久| 久久久中文字幕日本| 99久久人妻无码精品系列蜜桃| 久久99精品久久只有精品| 无码AV波多野结衣久久| 久久天天躁狠狠躁夜夜96流白浆 | 无码任你躁久久久久久| 久久久久无码中| 色欲综合久久躁天天躁| 久久噜噜久久久精品66| 久久亚洲中文字幕精品一区|