作業系統---之fork()函式

zxyhhjs2017發表於2018-04-24

【Linux】關於理解fork()函式的簡單例子

原創 2016年06月19日 00:13:18

1.fork()函式

fork()函式通過系統呼叫建立一個與原來程式幾乎完全相同的程式,這個新產生的程式稱為子程式。一個程式呼叫fork()函式後,系統先給新的程式分配資源,例如儲存資料和程式碼的空間。然後把原來的程式的所有值都複製到新的新程式中,只有少數值與原來的程式的值不同。相當於克隆了一個自己。需要注意的一點:就是呼叫fork函式之後,一定是兩個程式同時執行的程式碼段是fork函式之後的程式碼,而之前的程式碼以及由父程式執行完畢。下面來看一個很簡單的例子。
fork函式返回兩個值

  • 返回一個大於0的值給父程式
  • 返回0給子程式
  • 返回其他值說明fork失敗了

2.關於fork的一個簡單例子

#include<stdio.h>
#include<unistd.h>
int main()
{
    pid_t pid;
    int count = 0;
    pid = fork();   //fork一個程式
    if(pid == 0)
    {               //pid為0,
        printf("this is child process, pid is %d\n",getpid());//getpid返回的是當前程式的PID
        count+=2;
        printf("count = %d\n",count);
    }
    else if(pid > 0)
    {
        printf("this is father process, pid is %d\n",getpid());
        count++;
        printf("count = %d\n",count);
    }
    else
    {
        fprintf(stderr,"ERROR:fork() failed!\n");
    }
    return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25

下面是執行結果:
這裡寫圖片描述
  有人會對這個執行結果產生一種錯覺,就是程式中if語句的兩條分支if(pid == 0)和else if(pid > 0)都得到了執行,其實完全不是這麼回事,出現這種執行結果的原因是因為,在main()函式的第6行fork了一個程式,這個程式稱為原來程式的子程式,原來的那個程式稱為父程式,這個程式與原來的程式併發執行,誰先稅後沒有規律,由作業系統排程決定。
  我們用gdb工具對這個程式單步執行除錯一下,可能會對這個過程瞭解的更清晰一些。

3.使用gdb除錯父程式。

1.輸入gdb a.out然後輸入start開始除錯,此時終端顯示即將執行的程式碼
這裡寫圖片描述
2.輸入n,執行當前一行程式碼,同時顯示下一條將執行的程式碼
這裡寫圖片描述
即將建立一個子程式,當前程式為父程式。
3.再輸入n執行pid=fork()語句
這裡寫圖片描述
這個時候,終端上顯示

Detaching after fork from child process 2755.
this is child process, pid is 2755
count = 2
  • 1
  • 2
  • 3

這個時候,說明已經新建了一個子程式,子程式PID是2755,而且由於我們現在單步除錯的是父程式,並不影響子程式的執行,這個子程式只有幾行程式碼,這個時候已經執行完了,並且在終端上顯示了執行結果,就是下面兩行內容。

this is child process, pid is 2755
count = 2
  • 1
  • 2

4.這個時候,我們輸入p pid看一下fork函式返回給父程式的值是不是子程式的PID
這裡寫圖片描述
果然就是子程式的PID值。
5.輸入n接著執行判斷語句
這裡寫圖片描述
由於pid的值為2755,因此跳過了if(pid==0)分支內的語句,轉而判斷pid是否大於0
6.輸入n接著判斷pid是否大於0
這裡寫圖片描述
pid的值大於0,執行分支內的語句。
7.接著輸入n,直到程式正常結束
這裡寫圖片描述

上面是父程式的除錯過程,其實子程式也可以用gdb來除錯,下次再說。

4.使用ps aux命令檢視父程式和子程式

  ps aux命令可以檢視系統中正在執行的所有程式,不過我們這個例子程式碼很少,系統瞬間就能執行完畢,用ps aux命令根本捕捉不到。因此我們在程式碼中做一些修改。
  

#include<stdio.h>
#include<unistd.h>
int main()
{
    pid_t pid;
    int count = 0;
    pid = fork();   //fork一個程式
    if(pid == 0)
    {               //pid0,
        printf("this is child process, pid is %d\n",getpid());
        count+=2;
        printf("count = %d\n",count);
    }
    else if(pid > 0)
    {
        printf("this is father process, pid is %d\n",getpid());
        count++;
        printf("count = %d\n",count);
    }
    else
    {
        fprintf(stderr,"ERROR:fork() failed!\n");
    }
    sleep(10);//新加入的行,讓程式在這裡暫停10秒,父程式和子程式都會執行這行程式碼
    return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26

我們在第30行加入了一條語句,讓程式暫停10s
重新編譯程式,然後執行程式,輸入./a.out後,快速切換到另外一個終端(如果你手速慢的話,多暫停一會兒就可以),輸入ps aux檢視正在執行的程式。
執行程式:
這裡寫圖片描述

切換終端,輸入ps aux檢視程式
這裡寫圖片描述
可以看到a.out程式產生了兩個程式,父程式PID是2928,子程式PID是2929。


轉載:https://blog.csdn.net/ww1473345713/article/details/51708003

相關文章