理解C中的forks
我在理解以下简单C代码时遇到一些问题:理解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 为什么呢 编辑:直到现在我才意识到,
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()语义。)
- 一个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;
}