C語言fork一個進程 Linux

進程的相關知識筆記:

       進程是一個程序的執行過程。多個進程分時複用CPU,當分配給進程的時間片結束後,內核會收回進程對CPU的使用權,轉而給系統的其他進程執行,而之前的進程就需要進入睡眠態,相關的數據就會先保存起來,等候CPU的調度。所以一個進程的生命週期有很多不同的狀態,通常進程的狀態被劃分爲5種:初始態、就緒態、運行態、睡眠態、終止態。

       在系統中每一個進程都有一個進程id,簡稱pid (process id),進程有父子關係、兄弟關係,每一個進程都有一個父親,父進程的進程id,叫做ppid。所以系統裏面的進程會形成一個進程樹,使用pstree命令可以查看當前系統的進程樹。以前進程的頂端是init進程,進程號爲1,現在有的linux系統使用systemd作爲系統的頂級進程,進程號也是1,至於兩者的區別,可以谷歌查閱相關的資料,當我們fork一個進程後,代碼從fork後,分別由兩個進程執行,父子進程的執行順序無法預測。當子進程執行完,父進程沒有進行回收處理,就會出現殭屍進程(defunct進程),當父進程執行完,子進程還沒執行完,子進程就變成孤兒進程,這是systemd就會認領,負責回收處理。

下面就是一個利用fork函數,創建子進程的例子:

#include <stdio.h>  //標準的輸入輸出函數
#include <stdlib.h> //standard library標準庫函數頭文件
#include <unistd.h> //對於類 Unix 系統,unistd.h 中所定義的接口通常都是大量針對系統調用的封裝 fork、

int main()
{
    pid_t pid;
    
    pid=fork(); //創建一個進程,下面的代碼, 由兩個進程分別執行,父子進程執行順序無法預測
    // pid 在兩個不同的進程中,返回的結果不一樣
    
    // 這是異常情況
    if (pid==-1)
    {
        perror("fork失敗!");
        exit(1);
    }

    //返回大於0的進程就是父進程
    if(pid>0)  //父進程
    {
        printf("父進程: pid= %d , ppid=%d,子進程: %d \n", getpid(),getppid(),pid);

        sleep(1); //這裏延遲父進程程序,等子進程先執行完。
    }
    else if(pid==0)  //子進程
    { 
        printf("子進程: pid= %d , ppid=%d \n", getpid(),getppid());
    }

    printf("執行完成!\n"); //由兩個進程執行,當然輸出兩次

    return 0; //養成好習慣,返回程序執行狀態碼
}

請留意sleep(1); 這段代碼, 並嘗試註釋後,重新編譯一個,然後執行他們,看看有加sleep和沒有的區別,

有加sleep(1);會輸出:

       父進程: pid= 17571 , ppid=16415,子進程: 17572 
       子進程: pid= 17572 , ppid=17571 
       執行完成!
       執行完成!

注: 子進程先執行完,父進程還沒死,此時子進程ppid就是父進程的pid

沒有加sleep;可能會輸出:

       父進程: pid= 17580 , ppid=16415,子進程: 17581 
       執行完成!
       子進程: pid= 17581 , ppid=1 
       執行完成!

注: 父進程先執行完,子進程還沒,子進程被systemd接收,子進程的ppid就變成了1。

 

本文參考Linux編程基礎一書。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章