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!
"); 
    return 0; 
} 

输出:

Hello world!
Hello world!

执行fork函数后,父进程和子进程都会执行下一行代码和后面的代码,所以会输出两遍

计算hello打印的次数 

#include <stdio.h> 
#include <sys/types.h> 
int main() 
{ 
    fork(); 
    fork(); 
    fork(); 
    printf("hello
"); 
    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!
"); 

    // parent process because return value non-zero. 
    else
        printf("Hello from Parent!
"); 
} 
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
", ++x); 
    else
        printf("Parent has x = %d
", --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/

原文地址:https://www.cnblogs.com/xinrong2019/p/11838950.html