Golang協程實現流量統計系統(2)

 從進程開始,搜索和理解進程

Google 搜索關鍵詞: C fork example

 

什麼是fork

Fork系統調用用於創建一個稱爲子進程的新進程,該子進程與進行fork()調用的進程(父進程)同時運行。

創建新的子進程後,兩個進程都將在fork()系統調用之後執行下一條指令。

子進程使用與父進程相同的pc(程序計數器),相同的CPU寄存器,相同的打開文件。

 

fork返回值

它不帶任何參數,並返回一個整數值。以下是fork()返回的不同值。

 

負值:創建子進程失敗。

零:返回到新創建的子進程。

正值:返回給父級或調用者。該值包含新創建的子進程的進程ID。

 

寫點代碼

光看上面的解釋有點幹,來份代碼

#include <stdio.h> 
#include <sys/types.h> 
#include <unistd.h> 
int main() 
{ 

    // make two process which run same 
    // program after this instruction 
    fork(); 

    printf("Hello world!\n"); 
    return 0; 
} 

輸出:

Hello world!
Hello world!

執行fork函數後,父進程和子進程都會執行下一行代碼和後面的代碼,所以會輸出兩遍

 

計算hello打印的次數 

#include <stdio.h> 
#include <sys/types.h> 
int main() 
{ 
    fork(); 
    fork(); 
    fork(); 
    printf("hello\n"); 
    return 0; 
} 

 

 輸出

hello
hello
hello
hello
hello
hello
hello
hello

 

 hello打印的次數等於創建的進程數。

進程總數= 2^n,其中n是fork系統調用的數目。所以這裏n = 3,2^3 = 8

還不理解?我們來逐行分析

fork ();   // Line 1
fork ();   // Line 2
fork ();   // Line 3

       L1       // There will be 1 child process 
    /     \     // created by line 1.
  L2      L2    // There will be 2 child processes
 /  \    /  \   //  created by line 2
L3  L3  L3  L3  // There will be 4 child processes 
                // created by line 3

 

因此,總共有八個進程(新的子進程和一個原始進程)。

如果我們想將流程之間的關係表示爲樹層次結構,則如下所示:

主進程:P0

第一個fork函數創建的進程:P1

第二個fork函數創建的進程:P2、P3

第三個fork函數創建的進程:P4、P5、P6、P7

預測以下程序的輸出

#include <stdio.h> 
#include <sys/types.h> 
#include <unistd.h> 
void forkexample() 
{ 
    // child process because return value zero 
    if (fork() == 0) 
        printf("Hello from Child!\n"); 

    // parent process because return value non-zero. 
    else
        printf("Hello from Parent!\n"); 
} 
int main() 
{ 
    forkexample(); 
    return 0; 
} 

 

輸出:

1.
Hello from Child!
Hello from Parent!
     (or)
2.
Hello from Parent!
Hello from Child!

在上面的代碼中,創建了一個子進程,fork()在該子進程中返回0,並向父進程返回正整數。

在這裏,兩個輸出都是可能的,因爲父進程和子進程正在同時運行。 因此,我們不知道操作系統是首先控制父進程還是子進程。

 

父進程和子進程正在運行同一程序,但這並不意味着它們是相同的。 OS爲這兩個進程分配不同的數據和狀態,並且控制這些進程的流可以有所不同。

看下面的例子:

#include <stdio.h> 
#include <sys/types.h> 
#include <unistd.h> 

void forkexample() 
{ 
    int x = 1; 

    if (fork() == 0) 
        printf("Child has x = %d\n", ++x); 
    else
        printf("Parent has x = %d\n", --x); 
} 
int main() 
{ 
    forkexample(); 
    return 0; 
} 

 

輸出:

Parent has x = 0
Child has x = 2
     (or)
Child has x = 2
Parent has x = 0

這裏,一個進程中的全局變量更改不會影響其他兩個進程,因爲兩個進程的數據/狀態不同。而且父級和子級同時運行,因此有兩個輸出是可能的。

 

 

 

參考閱讀: 

1、https://www.geeksforgeeks.org/fork-system-call/

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