• <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>

            為生存而奔跑

               :: 首頁 :: 聯(lián)系 :: 聚合  :: 管理
              271 Posts :: 0 Stories :: 58 Comments :: 0 Trackbacks

            留言簿(5)

            我參與的團隊

            搜索

            •  

            積分與排名

            • 積分 - 326856
            • 排名 - 74

            最新評論

            閱讀排行榜

            評論排行榜

            1. #include <stdio.h>  
            2. #include <sys/wait.h>  
            3. #include <sys/types.h>  
            4. #include <unistd.h>  
            5.   
            6. int main(void)     
            7. {     
            8.    pid_t pid;     
            9.     
            10.     if ((pid = fork()) < 0)     
            11.     {     
            12.         fprintf(stderr,"Fork error!\n");     
            13.         exit(-1);     
            14.     }     
            15.     else if (pid == 0) /* first child */    
            16.     {      
            17.         if ((pid = fork()) < 0)     
            18.         {      
            19.             fprintf(stderr,"Fork error!\n");     
            20.             exit(-1);     
            21.         }     
            22.         else if (pid > 0)     
            23.             exit(0); /* parent from second fork == first child */    
            24.         /*   
            25.          * We're the second child; our parent becomes init as soon   
            26.          * as our real parent calls exit() in the statement above.   
            27.          * Here's where we'd continue executing, knowing that when   
            28.          * we're done, init will reap our status.   
            29.          */    
            30.         sleep(2);     
            31.         printf("Second child, parent pid = %d\n", getppid());     
            32.         exit(0);     
            33.     }     
            34.          
            35.     if (waitpid(pid, NULL, 0) != pid) /* wait for first child */    
            36.     {     
            37.         fprintf(stderr,"Waitpid error!\n");     
            38.         exit(-1);     
            39.     }     
            40.     
            41.     /*   
            42.      * We're the parent (the original process); we continue executing,   
            43.      * knowing that we're not the parent of the second child.   
            44.      */    
            45.     exit(0);     
            46. }     

            fork兩次在防止僵死方面來說,就是因為兒子進程先退出,孫子進程就被init接管了,實際上與最初的父進程脫離了關(guān)系,就不會僵死了。見APUE 的P151以下描述:

            回憶一下8 . 5節(jié)中有關(guān)僵死進程的討論。如果一個進程要f o r k一個子進程,但不要求它等待
            子進程終止,也不希望子進程處于僵死狀態(tài)直到父進程終止,實現(xiàn)這一要求的訣竅是調(diào)用f o r k
            兩次。程序8 - 5實現(xiàn)了這一點。
            在第二個子進程中調(diào)用s l e e p以保證在打印父進程I D時第一個子進程已終止。在f o r k之后,
            父、子進程都可繼續(xù)執(zhí)行——我們無法預(yù)知哪一個會先執(zhí)行。如果不使第二個子進程睡眠,則
            在f o r k之后,它可能比其父進程先執(zhí)行,于是它打印的父進程I D將是創(chuàng)建它的父進程,而不是
            i n i t進程(進程ID 1)。

            兩次fork的其它作用就是做daemon:

             

            1. void InitAsDaemon()     
            2. {     
            3.  if (Fork() > 0)     
            4.   exit(0);     
            5.     
            6.  setsid();     
            7.     
            8.  Signal(SIGINT, SIG_IGN);     
            9.  Signal(SIGHUP, SIG_IGN);     
            10.  Signal(SIGQUIT, SIG_IGN);     
            11.  Signal(SIGPIPE, SIG_IGN);     
            12.  Signal(SIGTTOU, SIG_IGN);     
            13.  Signal(SIGTTIN, SIG_IGN);     
            14.  Signal(SIGCHLD, SIG_IGN);     
            15.     
            16.  if (Fork() > 0)     
            17.   exit(0);     
            18.     
            19.  chdir("/");     
            20.  umask(0);     
            21. }  

            關(guān)于僵尸進程:

              在fork()/execve()過程中,假設(shè)子進程結(jié)束時父進程仍存在,而父進程fork()之前既沒安裝SIGCHLD信號處理函數(shù)調(diào)用waitpid()等待子進程結(jié)束,又沒有顯式忽略該信號,則子進程成為僵尸進程,無法正常結(jié)束,此時即使是root身份kill -9也不能殺死僵尸進程。補救辦法是殺死僵尸進程的父進程(僵尸進程的父進程必然存在),僵尸進程成為"孤兒進程",過繼給1號進程init,init始終會負責清理僵尸進程。

              僵尸進程是指的父進程已經(jīng)退出,而該進程dead之后沒有進程接受,就成為僵尸進程.(zombie)進程 
              怎樣產(chǎn)生僵尸進程的: 
              一個進程在調(diào)用exit命令結(jié)束自己的生命的時候,其實它并沒有真正的被銷毀,而是留下一個稱為僵尸進程(Zombie)的數(shù)據(jù)結(jié)構(gòu)(系統(tǒng)調(diào)用exit,它的作用是使進程退出,但也僅僅限于將一個正常的進程變成一個僵尸進程,并不能將其完全銷毀)。在Linux進程的狀態(tài)中,僵尸進程 
              是非常特殊的一種,它已經(jīng)放棄了幾乎所有內(nèi)存空間,沒有任何可執(zhí)行代碼,也不能被調(diào)度,僅僅在進程列表中保留一個位置,記載該進程的退 
              出狀態(tài)等信息供其他進程收集,除此之外,僵尸進程不再占有任何內(nèi)存空間。它需要它的父進程來為它收尸,如果他的父進程沒安裝SIGCHLD信 
              號處理函數(shù)調(diào)用wait或waitpid()等待子進程結(jié)束,又沒有顯式忽略該信號,那么它就一直保持僵尸狀態(tài),如果這時父進程結(jié)束了,那么init進程自動 
              會接手這個子進程,為它收尸,它還是能被清除的。但是如果如果父進程是一個循環(huán),不會結(jié)束,那么子進程就會一直保持僵尸狀態(tài),這就是為什么系統(tǒng)中有時會有很多的僵尸進程。 
              怎么查看僵尸進程: 
              利用命令ps,可以看到有標記為Z的進程就是僵尸進程。 
              怎樣來清除僵尸進程: 
              1.改寫父進程,在子進程死后要為它收尸。具體做法是接管SIGCHLD信號。子進程死后,會發(fā)送SIGCHLD信號給父進程,父進程收到此信號后,執(zhí)行waitpid()函數(shù)為子進程收尸。這是基于這樣的原理:就算父進程沒有調(diào)用wait,內(nèi)核也會向它發(fā)送SIGCHLD消息,盡管對的默認處理是忽略,如果想響應(yīng)這個消息,可以設(shè)置一個處理函數(shù)。 
              2.把父進程殺掉。父進程死后,僵尸進程成為"孤兒進程",過繼給1號進程init,init始終會負責清理僵尸進程.它產(chǎn)生的所有僵尸進程也跟著消失。
              =========================================== 
              在Linux中可以用 
              ps auwx 
              發(fā)現(xiàn)僵尸進程 
              a all w/ tty, including other users 所有窗口和終端,包括其他用戶的進程 
              u user-oriented 面向用戶(用戶友好) 
              -w,w wide output 寬格式輸出 
              x processes w/o controlling ttys 
              在僵尸進程后面 會標注 
              ps axf 
              看進程樹,以樹形方式現(xiàn)實進程列表 
              ps axm 
              會把線程列出來,在linux下進程和線程是統(tǒng)一的,是輕量級進程的兩種方式。 
              ps axu 
              顯示進程的詳細狀態(tài) 
              =========================================== 
              killall 
              kill -15 
              kill -9 
              一般都不能殺掉 defunct進程 
              用了kill -15,kill -9以后 之后反而會多出更多的僵尸進程 
              kill -kill pid 
              fuser -k pid 
              可以考慮殺死他的parent process, 
              kill -9 他的parent process 
              =========================================== 
              一個已經(jīng)終止,但是其父進程尚未對其進行善后處理(獲取終止子進程的有關(guān)信息、釋放它仍占用的資源)的進程被稱為僵死進程(Zombie Process)。 
              避免zombie的方法: 
              1)在SVR4中,如果調(diào)用signal或sigset將SIGCHLD的配置設(shè)置為忽略,則不會產(chǎn)生僵死子進程。另外,使用SVR4版的sigaction,則可設(shè)置SA_NOCLDWAIT標志以避免子進程僵死。 
              Linux中也可使用這個,在一個程序的開始調(diào)用這個函數(shù) 
              signal(SIGCHLD,SIG_IGN); 
              2)調(diào)用fork兩次。程序8 - 5 實現(xiàn)了這一點。 
              3)用waitpid等待子進程返回. 
              =========================================== 
              zombie進程是僵死進程。防止它的辦法,一是用wait,waitpid之類的函數(shù)獲得 
              進程的終止狀態(tài),以釋放資源。另一個是fork兩次 
              =========================================== 
              defunct進程只是在process table里還有一個記錄,其他的資源沒有占用,除非你的系統(tǒng)的process個數(shù)的限制已經(jīng)快超過了,zombie進程不會有更多的壞處。 
              可能唯一的方法就是reboot系統(tǒng)可以消除zombie進程。 
              =========================================== 
              任何程序都有僵尸狀態(tài),它占用一點內(nèi)存資源(也就是進程表里還有一個記錄),僅僅是表象而已不必害怕。如果程序有問題有機會遇見,解決大批量僵尸簡單有效的辦法是重起。kill是無任何效果的 
              fork與zombie/defunct" 
              在Unix下的一些進程的運作方式。當一個進程死亡時,它并不是完全的消失了。進程終止,它不再運行,但是還有一些殘留的小東西等待父進程收回。這些殘留的東西包括子進程的返回值和其他的一些東西。當父進程 fork() 一個子進程后,它必須用 wait() 或者 waitpid() 等待子進程退出。正是這個 wait() 動作來讓子進程的殘留物消失。 
              自然的,在上述規(guī)則之外有個例外:父進程可以忽略 SIGCLD 軟中斷而不必要 wait()。可以這樣做到(在支持它的系統(tǒng)上,比如Linux): 
            1. main()      
            2.     
            3.   {      
            4.     
            5.   signal(SIGCLD, SIG_IGN); /* now I don't have to wait()! */      
            6.     
            7.   .      
            8.     
            9.   .      
            10.     
            11.   fork();      
            12.     
            13.   fork();      
            14.     
            15.   fork(); /* Rabbits, rabbits, rabbits! */      
            16.     
            17.  }    
                現(xiàn)在,子進程死亡時父進程沒有 wait(),通常用 ps 可以看到它被顯示為“”。它將永遠保持這樣 直到 父進程 wait(),或者按以下方法處理。 
              這里是你必須知道的另一個規(guī)則:當父進程在它wait()子進程之前死亡了(假定它沒有忽略 SIGCLD),子進程將把 init(pid 1)進程作為它的父進程。如果子進程工作得很好并能夠控制,這并不是問題。但如果子進程已經(jīng)是 defunct,我們就有了一點小麻煩。看,原先的父進程不可能再 wait(),因為它已經(jīng)消亡了。這樣,init 怎么知道 wait() 這些 zombie 進程。 
              答案:不可預(yù)料的。在一些系統(tǒng)上,init周期性的破壞掉它所有的defunct進程。在另外一些系統(tǒng)中,它干脆拒絕成為任何defunct進程的父進程,而是馬上毀滅它們。如果你使用上述系統(tǒng)的一種,可以寫一個簡單的循環(huán),用屬于init的defunct進程填滿進程表。這大概不會令你的系統(tǒng)管理員很高興吧? 
              你的任務(wù):確定你的父進程不要忽略 SIGCLD,也不要 wait() 它 fork() 的所有進程。不過,你也未必 要 總是這樣做(比如,你要起一個 daemon 或是別的什么東西),但是你必須小心編程,如果你是一個 fork() 的新手。另外,也不要在心理上有任何束縛。 
              總結(jié): 
              子進程成為 defunct 直到父進程 wait(),除非父進程忽略了 SIGCLD 。 
              更進一步,父進程沒有 wait() 就消亡(仍假設(shè)父進程沒有忽略 SIGCLD )的子進程(活動的或者 defunct)成為 init 的子進程,init 用重手法處理它們。
            zt:http://blog.csdn.net/eroswang/archive/2008/11/19/3333617.aspx
            posted on 2011-03-17 21:56 baby-fly 閱讀(869) 評論(0)  編輯 收藏 引用 所屬分類: Ubuntu&Linux
            久久人人爽人人人人爽AV| 日产精品99久久久久久| 色婷婷噜噜久久国产精品12p| 思思久久精品在热线热| 人妻无码αv中文字幕久久琪琪布 人妻无码久久一区二区三区免费 人妻无码中文久久久久专区 | 99精品久久久久中文字幕| 国产精品热久久无码av| 亚洲综合精品香蕉久久网| 久久99国产一区二区三区| 欧美牲交A欧牲交aⅴ久久| 久久综合成人网| 91精品国产91久久综合| 超级97碰碰碰碰久久久久最新| 91精品国产9l久久久久| 狠狠色丁香久久婷婷综合| 国产精品美女久久久久av爽| 无码人妻精品一区二区三区久久久| 国产精久久一区二区三区| 精品蜜臀久久久久99网站| 久久精品桃花综合| 久久综合九色综合久99| 国产成人精品久久| 国产欧美一区二区久久| 久久精品国产亚洲av麻豆色欲| 久久久国产视频| 香蕉aa三级久久毛片| 国产午夜精品久久久久九九| 99久久er这里只有精品18| 国产成人精品综合久久久久| 午夜精品久久久久久| 久久免费视频6| 久久久久无码中| 久久久久久国产精品免费免费| 国产精品激情综合久久| 88久久精品无码一区二区毛片| 久久精品国产秦先生| 亚洲午夜久久影院| 久久播电影网| 中文字幕精品久久| 久久夜色精品国产亚洲| 7777久久久国产精品消防器材|