代码之家  ›  专栏  ›  技术社区  ›  devoured elysium

理解C中的forks

  •  1
  • devoured elysium  · 技术社区  · 14 年前

    我在理解以下简单的C代码时遇到了一些困难:

    int main(int argc, char *argv[]) {
        int n=0;
        fork();
        n++;
        printf("hello: %d\n", n);
    }
    

    我现在对 fork 从那一行代码开始,它将把剩下的代码分成2部分,然后并行运行,直到“没有更多的代码”可以执行为止。

    从棱镜上看,叉子后面的代码是:

    (一)

        n++;                       //sets n = 1
        printf("hello: %d\n", n);  //prints "hello: 1"
    

    (二)

        n++;                       //sets n = 2
        printf("hello: %d\n", n);  //prints "hello: 2"
    

    不过,这两张照片

    hello: 1
    

    为什么?

    编辑: 直到现在我才意识到,与线程相反,进程不共享相同的内存。对吗?如果是,那就是原因。

    7 回复  |  直到 14 年前
        1
  •  3
  •   ThiefMaster    14 年前

    fork() 启动新进程,不共享变量/内存位置。 它与执行 ./yourprogram 在一个shell中两次,假设程序做的第一件事是分叉。

        2
  •  7
  •   cababunga    14 年前

    fork()之后有两个进程,每个进程都有自己的“n”变量。

        3
  •  2
  •   vpit3833    14 年前

    在fork()调用结束时,两个进程可能都引用了同一个n的副本。但是在n++中,每个进程都得到了自己的副本n=0。在n++结束时,两个进程中的n都变为1。printf语句输出该值。

        4
  •  1
  •   frast    14 年前

    实际上,您生成了同一个program的新进程。这不是封闭式的东西。您可以使用管道在父级和子级之间交换数据。

        5
  •  1
  •   bmargulies    14 年前

    你确实在编辑中回答了你自己的问题。

        6
  •  1
  •   MJB    14 年前

    检查这段代码,一切都应该更清楚(如果不知道某个函数的作用,请参见手册页):

    #include <stdio.h>
    #include <unistd.h>
    #include <stdlib.h>
    
    int count = 1;
    
    int main(int argc, char *argv[]) {
    
        // set the "startvalue" to create the random numbers
        srand(time(NULL));
        int pid;
    
        // as long as count is <= 50
        for (count; count<=50; count++) {
    
            // create new proccess if count == 9
            if (count==9) {
                pid = fork();
                // reset start value for generating the random numbers
                srand(time(NULL)+pid);
            }
    
            if (count<=25) {
                // sleep for 300 ms
                usleep(3*100000);
            } else {
                // create a random number between 1 and 5
                int r = ( rand() % 5 ) + 1;
                // sleep for r ms
                usleep(r*100000);
            }
    
            if (pid==0) {
                printf("Child:  count:%d    pid:%d\n", count, pid);
            } else if (pid>0) {
                printf("Father: count:%d    pid:%d\n", count, pid);
            }
        }
    
    
        return 0;
    }
    

    快乐编码;-)

        7
  •  1
  •   DigitalRoss    14 年前

    系统调用分叉的不仅仅是执行线程:分叉的也是数据空间。你有两个 n个 在那一点上的变量。

    以下是一些有趣的事情:

    • fork()s必须考虑未写入的输出缓冲区的程序。它们可以在叉之前被刷新,或者在叉之后被清除,或者程序可以退出()而不是退出()以至少避免退出时的自动缓冲区刷新。
    • Fork通常使用 书面复制 以避免不必要地复制不会在子级中使用的大数据内存。
    • 最后,另一个电话 vfork() 在推出i 4.0BSD之后消失了一段时间之后,在大多数当前的Unix版本中重新出现。Vfork()不会假装复制数据空间,因此实现速度甚至比write fork()上的copy更快。(它在Linux中的实现可能不是由于速度原因,而是因为一些程序实际上依赖于vfork()语义。)