Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/68.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
理解C中的forks_C_Unix_Fork - Fatal编程技术网

理解C中的forks

理解C中的forks,c,unix,fork,C,Unix,Fork,我在理解以下简单C代码时遇到一些问题: int main(int argc, char *argv[]) { int n=0; fork(); n++; printf("hello: %d\n", n); } 我目前对fork的理解是,从这一行代码开始,它将把其余的代码拆分为2,并行运行,直到“没有更多的代码”可执行 从这个棱柱体来看,fork后面的代码是: (a) (b) 然而,发生的事情是,这两种方法 hello: 1 为什么呢 编辑:直到现在我才意识到,

我在理解以下简单C代码时遇到一些问题:

int main(int argc, char *argv[]) {
    int n=0;
    fork();
    n++;
    printf("hello: %d\n", n);
}
我目前对
fork
的理解是,从这一行代码开始,它将把其余的代码拆分为2,并行运行,直到“没有更多的代码”可执行

从这个棱柱体来看,fork后面的代码是:

(a)

(b)

然而,发生的事情是,这两种方法

hello: 1
为什么呢


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

实际上,您生成了一个相同程序的新进程。这不是一种结束式的事情。您可以使用管道在父级和子级之间交换数据。

实际上,您生成了一个相同程序的新进程。这不是一种结束式的事情。您可以使用管道在父级和子级之间交换数据。

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

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

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

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

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

这一切带来了一些有趣的事情:

  • 一个Frk()的程序必须考虑不成文的输出缓冲区。它们可以在fork之前刷新,也可以在fork之后清除,或者程序可以_exit()而不是exit(),以至少避免在exit时自动刷新缓冲区
  • Fork通常通过写时复制来实现,以避免不必要地复制不会在子级中使用的大型数据内存
  • 最后,在引入i 4.0BSD后消失了一段时间后,大多数当前Unix版本中都恢复了另一个调用vWork()。vWork()不会假装复制数据空间,因此实现速度甚至可以比write fork()上的复制更快。(它在Linux中的实现与其说是由于速度原因,不如说是因为一些程序实际上依赖vfork()语义。)

系统调用分叉多于执行线程:数据空间也分叉。在这一点上有两个n变量

这一切带来了一些有趣的事情:

  • 一个Frk()的程序必须考虑不成文的输出缓冲区。它们可以在fork之前刷新,也可以在fork之后清除,或者程序可以_exit()而不是exit(),以至少避免在exit时自动刷新缓冲区
  • Fork通常通过写时复制来实现,以避免不必要地复制不会在子级中使用的大型数据内存
  • 最后,在引入i 4.0BSD后消失了一段时间后,大多数当前Unix版本中都恢复了另一个调用vWork()。vWork()不会假装复制数据空间,因此实现速度甚至可以比write fork()上的复制更快。(它在Linux中的实现与其说是由于速度原因,不如说是因为一些程序实际上依赖vfork()语义。)
fork()
启动一个新进程,不共享变量/内存位置。 这与在一个shell中执行两次
/yourprogram
时发生的情况非常相似,假设程序做的第一件事就是分叉。

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

在fork()调用结束时,两个进程可能引用n的同一个副本。但是在n++,每个都有自己的拷贝,n=0。在n++的末尾;n在这两个过程中都变为1。printf语句输出这个值。

在fork()调用结束时,两个进程可能引用了n的同一个副本。但是在n++,每个都有自己的拷贝,n=0。在n++的末尾;n在这两个过程中都变为1。printf语句输出此值。

检查此代码,一切都应该更清楚(如果不知道某个函数的功能,请参阅手册页):

#包括
#包括
#包括
整数计数=1;
int main(int argc,char*argv[]){
//设置“startvalue”以创建随机数
srand(时间(空));
int-pid;

//只要count是检查此代码,所有内容都应该更清晰(如果您不知道某个函数的功能,请参阅手册页):

#包括
#包括
#包括
整数计数=1;
int main(int argc,char*argv[]){
//设置“startvalue”以创建随机数
srand(时间(空));
int-pid;

//只要count是Yes,就对了。您回答了自己的问题。不要忘记将您自己的答案作为答案发布。即使这些是线程,您的期望也是错误的。如果没有任何内存同步操作,两个线程都会打印1(和
n
之后包含值2)这将是一个完全有效的行为。是的,没错。您回答了自己的问题。不要忘记将您自己的答案作为答案发布。即使这些是线程,您的期望也是错误的。如果没有任何内存同步操作,两个线程都会打印1(并且
n
之后包含值2)这将是一个完全有效的行为。这个答案遗漏了一些关键概念。这个答案遗漏了一些关键概念。你在forks()中这样说's call end这两个进程都引用了n的同一个副本。这是如何工作的?它们不是在不同的进程中吗?我猜想,因为包括Linux在内的大多数现代系统都是在写时复制的,只有在写时才会创建n的副本。如果正在讨论的Linux在fork()复制,我可能会错.您说在forks()的调用结束时,两个进程都引用t
    n++;                       //sets n = 2
    printf("hello: %d\n", n);  //prints "hello: 2"
hello: 1
#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;
}