<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          有兩個(gè)這樣的進(jìn)程:僵尸進(jìn)程&孤兒進(jìn)程,藍(lán)瘦香菇

          共 3208字,需瀏覽 7分鐘

           ·

          2020-07-31 16:12



          點(diǎn)擊「閱讀原文」查看良許原創(chuàng)精品視頻。

          鏈接:https://juejin.im/post/5f20fbeae51d45348675fa78

          那時(shí)剛寫(xiě)公眾號(hào),當(dāng)時(shí)記錄的學(xué)習(xí)筆記,現(xiàn)在看來(lái),之前記錄的有一個(gè)錯(cuò)誤的地方,當(dāng)時(shí)也沒(méi)察覺(jué)到。

          寫(xiě)錯(cuò)了就要改嘛,程序員也不能怕錯(cuò)~

          不知道大家看自己幾年前的做事情,有的時(shí)候有沒(méi)有一種感覺(jué),這是我做的嗎???

          好吧,有點(diǎn)嫌棄當(dāng)時(shí)的自己~

          直接進(jìn)入正題吧,父子進(jìn)程之間到底有啥關(guān)系?

          進(jìn)程

          先來(lái)說(shuō)下什么是進(jìn)程:

          來(lái)看下百度是怎么說(shuō)的:

          光看說(shuō)的不夠形象,在windows系統(tǒng)中,它長(zhǎng)這樣:

          在Mac系統(tǒng)中,它長(zhǎng)這樣:

          Linux中是這樣的:(有點(diǎn)長(zhǎng)截圖一部分好了)

          [root@iz2ze76ybn73dvwmdij06zz?~]#?ps?-ef
          UID????????PID??PPID??C?STIME?TTY??????????TIME?CMD
          root?????????1?????0??0?5月20?????????00:00:33?/usr/lib/systemd/systemd?--system?--deserialize?21
          root?????????2?????0??0?5月20?????????00:00:00?[kthreadd]
          root?????????3?????2??0?5月20?????????00:00:06?[ksoftirqd/0]
          root?????????5?????2??0?5月20?????????00:00:00?[kworker/0:0H]
          root?????????7?????2??0?5月20?????????00:00:02?[migration/0]
          root?????????8?????2??0?5月20?????????00:00:00?[rcu_bh]
          root?????????9?????2??0?5月20?????????00:30:40?[rcu_sched]
          root????????10?????2??0?5月20?????????00:00:17?[watchdog/0]
          root????????11?????2??0?5月20?????????00:00:16?[watchdog/1]
          root????????12?????2??0?5月20?????????00:00:02?[migration/1]
          root????????13?????2??0?5月20?????????00:00:03?[ksoftirqd/1]
          root????????15?????2??0?5月20?????????00:00:00?[kworker/1:0H]
          root????????17?????2??0?5月20?????????00:00:00?[kdevtmpfs]
          root????????18?????2??0?5月20?????????00:00:00?[netns]
          root????????19?????2??0?5月20?????????00:00:01?[khungtaskd]
          root????????20?????2??0?5月20?????????00:00:00?[writeback]
          root????????21?????2??0?5月20?????????00:00:00?[kintegrityd]
          root????????22?????2??0?5月20?????????00:00:00?[bioset]
          root????????23?????2??0?5月20?????????00:00:00?[kblockd]

          OK,以上每一行都是對(duì)一個(gè)進(jìn)程的描述,來(lái)具體看一下每個(gè)參數(shù)的含義:

          標(biāo)示描述
          UID用戶(hù)ID
          PID進(jìn)程ID
          PPID父進(jìn)程ID
          C進(jìn)程占cpu百分比
          STIME進(jìn)程啟動(dòng)的時(shí)間
          TTY終端機(jī)位置
          TIME實(shí)際使用cpu的時(shí)間
          CMD命令以及參數(shù)

          我們現(xiàn)在知道了每個(gè)參數(shù)的含義,既然講到進(jìn)程嘛,首先,進(jìn)程ID是唯一的并且是非負(fù)數(shù)的,但是進(jìn)程ID是可以復(fù)用的,畢竟進(jìn)程也會(huì)終止。

          可以看到?jīng)]有進(jìn)程PID是0的,這是為什么呢?黑人問(wèn)號(hào)臉?

          0一般來(lái)說(shuō)是系統(tǒng)進(jìn)程,屬于內(nèi)核的一部分,不執(zhí)行任何磁盤(pán)上的程序。

          fork

          一個(gè)進(jìn)程可以通過(guò)調(diào)用fork函數(shù)創(chuàng)建新的進(jìn)程,被創(chuàng)建出來(lái)的這個(gè)進(jìn)程就叫子進(jìn)程。

          這里需要注意一下,fork函數(shù)的返回值父子進(jìn)程區(qū)別。

          • 子進(jìn)程 :返回值是0,返回0的理由是子進(jìn)程的父進(jìn)程是可以唯一確定的,通過(guò)getppid方法可以獲取到父進(jìn)程id。
          • 父進(jìn)程 : 返回的是新創(chuàng)建的子進(jìn)程的id,因?yàn)楦高M(jìn)程可以有多個(gè)子進(jìn)程,也沒(méi)有這樣的函數(shù)可以獲取該線(xiàn)程的子線(xiàn)程的所有id。

          下邊的話(huà)我們來(lái)驗(yàn)證一下上說(shuō)的這一段話(huà)。準(zhǔn)備好腳本。

          #include?
          #include?
          #include?

          int?main(int?argc,?char?const?*argv[])
          {

          ????pid_t?p1?=?fork();

          ????printf("%d\n",p1);

          ????if(p1?>?0)
          ????{
          ????????printf("父進(jìn)程?pid?=?%d,?p1?=?%d\n",?getpid(),?p1);
          ????}
          ????else
          ????{
          ????????printf("子進(jìn)程?pid?=?%d?,?ppid?=?%d,?p1?=?%d\n",?getpid(),?getppid(),?p1);
          ????}

          ????return?0;
          }

          運(yùn)行看結(jié)果:

          [root@iz2ze76ybn73dvwmdij06zz?~]#?./fork2
          10213
          父進(jìn)程?pid?=?10212,?p1?=?10213
          0
          子進(jìn)程?pid?=?10213?,?ppid?=?10212,?p1?=?0

          通過(guò)上面的小例子我們可以看到父進(jìn)程的返回值是子進(jìn)程的ID,子進(jìn)程的返回是0。

          孤兒進(jìn)程

          孤兒我們都懂就是。。。

          是的,沒(méi)錯(cuò)孤兒進(jìn)程也是這樣的,就是沒(méi)有父進(jìn)程的進(jìn)程。當(dāng)然創(chuàng)建的時(shí)候肯定是要先創(chuàng)建父進(jìn)程了,當(dāng)父進(jìn)程退出時(shí),它的子進(jìn)程們(一個(gè)或者多個(gè))就成了孤兒進(jìn)程了。

          接下來(lái)在繼續(xù)做一個(gè)小測(cè)試,讓父進(jìn)程現(xiàn)退出。準(zhǔn)備好腳本。

          [root@iz2ze76ybn73dvwmdij06zz?~]#?cat?guer.c
          #include?
          #include?
          #include?
          #include?


          int?main()
          {
          ????pid_t?pid?=?fork();

          ????if?(pid??perror("fork?error;");
          ????????exit(1);
          ????}?else?if?(pid?==?0)?{
          ?sleep(5);
          ????????printf?("子進(jìn)程?:?[?pid]?=?%d?,?父進(jìn)程?[ppid]?=?%d\n",getpid(),getppid());
          ????????exit(0);

          ????}?else?if?(pid?>?0)?{
          ?printf("我是父線(xiàn)程,我先退出一步~\n");
          ?exit(0);

          ????}
          ??return?0;
          }

          執(zhí)行并看結(jié)果:

          到這里估計(jì)很多童鞋估計(jì)已經(jīng)看懂了,父進(jìn)程退出后,子進(jìn)程被一個(gè)進(jìn)程ID為1的進(jìn)程領(lǐng)養(yǎng)的。還挺好這個(gè)結(jié)果,至少還是有人管的,被暖到了~ 進(jìn)程id為1的進(jìn)程是init進(jìn)程,每當(dāng)有孤兒進(jìn)程出現(xiàn)時(shí),init進(jìn)程就會(huì)收養(yǎng)它并成為它的父進(jìn)程 ,來(lái)照顧它以孤兒進(jìn)程以后的生活。

          危害

          因?yàn)楣聝哼M(jìn)程會(huì)被init進(jìn)程接管,所以孤兒進(jìn)程是沒(méi)有危害的。

          僵尸進(jìn)程

          和孤兒進(jìn)程相反的是,這次是子進(jìn)程先退出,而父進(jìn)程又沒(méi)有去處理回收釋放子進(jìn)程的資源,這個(gè)時(shí)候子進(jìn)程就成了僵尸進(jìn)程。

          先準(zhǔn)備好代碼:

          [root@iz2ze76ybn73dvwmdij06zz?~]#?cat?zombie.c
          ??#include?
          ??#include?
          ??#include?
          ??#include?

          ??int?main()
          ??{
          ??????pid_t?pid;
          ??????pid?=?fork();
          ?????if?(pid??????{
          ?????????perror("fork?error:");
          ?????????exit(1);
          ?????}
          ?????else?if?(pid?==?0)
          ?????{
          ?????????printf("我是子進(jìn)程,我要先退出一步了.\n");
          ??printf("子進(jìn)程?id?:?%d\n"?,getpid());
          ?????????exit(0);
          ?????}?else?{
          ?????????printf("我是父進(jìn)程,我先睡2秒\n");
          ?????????printf("父進(jìn)程?id?:?%d\n"?,getpid());

          ?????????sleep(2);

          ?????????while(2);?//來(lái)個(gè)死循環(huán),不退出的那種
          ????}


          ???return?0;
          ?}

          運(yùn)行看下結(jié)果:

          再來(lái)開(kāi)一個(gè)終端看下進(jìn)程結(jié)果:

          大家可以看到,子進(jìn)程并沒(méi)有完全退出,釋放資源,而是變成了僵尸進(jìn)程。

          危害

          資源上是占用不了什么資源。但是通常系統(tǒng)的進(jìn)程數(shù)量都是有限制的,如果有大量的僵尸進(jìn)程占用進(jìn)程號(hào),導(dǎo)致新的進(jìn)程無(wú)法創(chuàng)建,這個(gè)危害類(lèi)似于占個(gè)坑,不辦事。

          處理

          1.干掉父進(jìn)程

          干掉父進(jìn)程后,讓剩下的子進(jìn)程成為孤兒進(jìn)程,成為孤兒進(jìn)程后就和我們上面說(shuō)的一樣了,由init進(jìn)程來(lái)領(lǐng)養(yǎng)這些進(jìn)程,并且來(lái)處理這些進(jìn)程的資源釋放等工作。

          2.父進(jìn)程調(diào)用wait或waitpid

          等函數(shù)等待子進(jìn)程結(jié)束,這會(huì)導(dǎo)致父進(jìn)程掛起。執(zhí)行wait()或 waitpid()系統(tǒng)調(diào)用,則子進(jìn)程在終止后會(huì)立即把它在進(jìn)程表中的數(shù)據(jù)返回給父進(jìn)程,此時(shí)系統(tǒng)會(huì)立即刪除該進(jìn)入點(diǎn)。在這種情形下就不會(huì)產(chǎn)生defunct進(jìn)程。

          3.fork兩次

          第一次 fork : 父進(jìn)程fork一個(gè)子進(jìn)程

          第二次 fork : 子進(jìn)程fork一個(gè)孫進(jìn)程后退出

          那么孫進(jìn)程被init接管,當(dāng)孫進(jìn)程結(jié)束后,init會(huì)回收。

          但子進(jìn)程的回收還要自己做。

          4.signal函數(shù)

          父進(jìn)程來(lái)處理:用signal函數(shù)為SIGCHLD安裝handler,在子進(jìn)程結(jié)束后,父進(jìn)程會(huì)收到該信號(hào),可以在handler中調(diào)用wait回收。

          內(nèi)核來(lái)處理: 如果父進(jìn)程不關(guān)心子進(jìn)程什么時(shí)候結(jié)束,可以通過(guò)以下兩個(gè)函數(shù)通知內(nèi)核自己不感興趣子進(jìn)程的結(jié)束,此時(shí),子進(jìn)程結(jié)束后,內(nèi)核會(huì)回收并不再給你父進(jìn)程發(fā)信號(hào)。

          • signal(SIGCLD, SIG_IGN)
          • signal(SIGCHLD, SIG_IGN)

          總結(jié)

          本來(lái)以為簡(jiǎn)單的一個(gè)問(wèn)題,沒(méi)想到這個(gè)篇幅其實(shí)也不算短,所以感覺(jué)程序員真的不能說(shuō)一個(gè)什么知識(shí)點(diǎn)就簡(jiǎn)單,很容易理解啊,一旦你想要深入也是需要一定的時(shí)間花費(fèi)和精力的~

          參考:

          • 《UNIX環(huán)境高級(jí)編程(中文第三版)》

          • http://suo.im/6tOqJz

          • http://suo.im/67gdou

          良許個(gè)人微信


          添加良許個(gè)人微信即送3套程序員必讀資料


          → 精選技術(shù)資料共享

          → 高手如云交流社群





          本公眾號(hào)全部博文已整理成一個(gè)目錄,請(qǐng)?jiān)诠娞?hào)里回復(fù)「m」獲??!

          推薦閱讀:

          這個(gè)只有1.5M的軟件,能讓你的網(wǎng)速快3倍

          在Linux系統(tǒng)中使用Vim讀寫(xiě)遠(yuǎn)程文件

          漫畫(huà):什么是 “設(shè)計(jì)模式” ?


          5T技術(shù)資源大放送!包括但不限于:C/C++,Linux,Python,Java,PHP,人工智能,單片機(jī),樹(shù)莓派,等等。在公眾號(hào)內(nèi)回復(fù)「1024」,即可免費(fèi)獲?。。?/span>


          瀏覽 95
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  97色色网站 | 找找色亚洲 | 翔田千里系列无码流出 | 学生妹一级大片 | 色噜噜人妻av中文字幕 |