当前位置: 首页>>代码示例 >>用法及示例精选 >>正文


C语言 fork()用法及代码示例


叉系统调用用于创建一个称为子进程的新进程,该子进程与进行fork()调用的进程(父进程)同时运行。创建新的子进程后,两个进程将在fork()系统调用之后执行下一条指令。子进程使用与父进程相同的pc(程序计数器),相同的CPU寄存器,相同的打开文件。

它不带任何参数,并返回一个整数值。以下是fork()返回的不同值。

负值:创建子进程失败。
:返回到新创建的子进程。
正值:返回家长或来电者。该值包含新创建的子进程的进程ID。


creating a fork process

请注意,以上程序无法在Windows环境中编译。

  1. 预测以下程序的输出:
    #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!
    

  2. 计算您好打印的次数:
    #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”的打印次数等于创建的进程数。进程总数= 2n,其中n是fork系统调用的数量。所以这里n = 3,23= 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
    第二叉创建的进程:P2,P3
    第三叉创建的进程:P4,P5,P6,P7

                 P0
             /   |   \
           P1    P4   P2
          /  \          \
        P3    P6         P5
       /
     P7
    
  3. 预测以下程序的输出:
    #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为这两个进程分配不同的数据和状态,并且这些进程的控制流可能不同。请参见下一个示例:

  4. 预测以下程序的输出:
    #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
    

    这里,一个进程中的全局变量更改不会影响其他两个进程,因为两个进程的数据/状态不同。而且父级和子级同时运行,因此有两个输出是可能的。

fork() vs exec()

fork系统调用将创建一个新进程。 fork()创建的新流程是当前流程的副本,但返回的值除外。 exec()系统调用用新程序替换当前进程。

行使:

  1. 一个进程执行以下代码:
    for (i = 0; i < n; i++) 
        fork();

    创建的子进程总数为:(GATE-CS-2008)
    (A)n
    (B)2^n-1
    (C)2^n
    (D)2 ^(n + 1)-1;

    请参阅此解决方案。

  2. 考虑以下代码片段:
    if (fork() == 0) { 
        a = a + 5; 
        printf("%d, %d\n", a, &a); 
    } 
    else { 
        a = a -5; 
        printf("%d, %d\n", a, &a); 
    }

    令u,v为父进程打印的值,x,y为子进程打印的值。以下哪一项是TRUE? (GATE-CS-2005)
    (A)u = x + 10和v = y
    (B)u = x + 10和v!= y
    (C)u + 10 = x和v = y
    (D)u + 10 = x和v!= y
    请参阅此解决方案。

  3. 预测以下程序的输出。

    #include <stdio.h> 
    #include <unistd.h> 
    int main() 
    { 
        fork(); 
        fork() && fork() || fork(); 
        fork(); 
      
        printf("forked\n"); 
        return 0; 
    }

    看到这个解决方案

相关文章:
演示fork()和pipe()的C程序
C语言中的僵尸和孤立进程
fork()和使用它创建的内存共享黑白进程。

参考文献:
http://www.csl.mtu.edu/cs4411.ck/www/NOTES/process/fork/create.html




注:本文由纯净天空筛选整理自 fork() in C。非经特殊声明,原始代码版权归原作者所有,本译文未经允许或授权,请勿转载或复制。