C语言 通过一个简单的例子了解C的fork()
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/15262860/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Understanding C's fork() through a simple example
提问by Locke McDonnell
#include <stdio.h>
int num = 0;
int main(int argc, char*argv[]){
int pid;
pid = fork();
printf("%d", num);
if(pid == 0){ /*child*/
num = 1;
}else if(pid > 0){ /*parent*/
num = 2;
}
printf("%d", num);
}
I'm having trouble understanding why the possible outputs would be 0102 or 0012 or 0201 or 0021.
我无法理解为什么可能的输出是 0102 或 0012 或 0201 或 0021。
Here is what I (think) it should be producing. It hits the first printf statement and no matter what child or parent gets executed first, num hasn't been modified so 0 first. THEN next is either 1 or 2, then the next process executes so starts with 0 again (copied from the parent) and then either a 1 or 2 again. So the possible outputs should be:
这是我(认为)它应该产生的。它命中第一个 printf 语句,无论哪个孩子或父母先执行,num 都没有被修改,所以首先是 0。然后下一个是 1 或 2,然后下一个进程执行,因此再次从 0 开始(从父级复制),然后再次从 1 或 2 开始。所以可能的输出应该是:
0101 or 0102 or 0201 or 0202
0101 或 0102 或 0201 或 0202
回答by Samuel Edwin Ward
In both the parent and the child, num is 0 for the first printf. In both the parent and the child, 0 is printed followed by the other value. In the parent process, the other value is 2. In the child process, the other value is 1.
在父级和子级中,第一个 num 都是 0 printf。在父级和子级中,打印 0 后跟另一个值。在父进程中,另一个值为 2。在子进程中,另一个值为 1。
However, the important thing to note is that although each process has an enforced order that zero has to be printed before the other number, there is no restriction on the printing of the two processes relative to each other.
然而,需要注意的重要一点是,虽然每个进程都有一个强制命令,即必须在另一个数字之前打印零,但对两个进程的相对打印没有限制。
Here's a real-life analogy: Suppose my coworker and each I leave work at the same time, stop at the grocery store, and then arrive home. We know I was at the store before I was at my home, and we know he was at the grocery store before he was at his home. But we don't know who was at the grocery store first, or who was at home first. We could each arrive at the grocery store around the same time and then each arrive home around the same time, or maybe he's delayed and I get the grocery store and home before he even gets to the store.
这是一个现实生活中的类比:假设我的同事和我每个人同时下班,在杂货店停下来,然后到家。我们知道在我回家之前我在商店,我们知道他在他家之前在杂货店。但我们不知道谁先在杂货店,或谁先在家。我们可以每个人大约在同一时间到达杂货店,然后每个人大约在同一时间到家,或者他可能延误了,我什至在他到达商店之前就到达了杂货店和家。
Something that won't happen is the printing of 1 or 2 more than once. Although after forkreturns we have two processes running conceptually at once, and the timing of their events relative to each other is unspecified, the order of events in each process is well defined. Each process will set numto either 1 or 2 before printing it again, and because forkis defined to return 0 in the child and the child's pid in the parent, they will each set it to different values.
不会发生的事情是不止一次打印 1 或 2。虽然在fork返回后我们有两个进程在概念上同时运行,并且它们的事件相对于彼此的时间没有指定,但每个进程中的事件顺序是明确定义的。每个进程num在再次打印之前将设置为 1 或 2,并且因为fork被定义为在子进程中返回 0,在父进程中返回子进程的 pid,所以它们将每个进程设置为不同的值。
There is, actually, another reasonable output: 00. If forkis unable to create a new process, it returns -1. In this case program will print 0, the ifand else ifs will fail because -1 is neither 0 nor greater than 0, num is not changed, and the program prints 0again.
实际上,还有另一个合理的输出:00. 如果fork无法创建新进程,则返回 -1。在这种情况下 program 将打印0,ifand else ifs 将失败,因为 -1 既不是 0 也不是大于 0, num 没有改变,并且程序0再次打印。
If you want to learn a lot about the definition of the ordering of effects in C programs, the key words to search for are "sequence points". In this program it's fairly straightforward (aside from the fact that we have two copies running at once), but it can sometimes be less obvious.
如果你想了解很多关于 C 程序中效果排序的定义,要搜索的关键词是“序列点”。在这个程序中,它相当简单(除了我们同时运行两个副本这一事实之外),但有时可能不那么明显。
回答by Samuel Edwin Ward
This is not the problem with fork(). It is the printf()since printf()is buffered. Normally the buffer is flushed when it encounters a newline character at the end, '\n'. However since you have omitted this, the contents of the buffer stays and is not flushed. In the end, both processes (the original and the child) will have the output buffer with 0 or 1 in it. When it eventually gets flushed, you'll see this in both processes.
这不是fork(). 这是printf()因为printf()被缓冲。通常,缓冲区在末尾遇到换行符 '\n' 时会刷新。但是,由于您忽略了这一点,缓冲区的内容会保留并且不会被刷新。最后,两个进程(原始进程和子进程)都将拥有包含 0 或 1 的输出缓冲区。当它最终被刷新时,您将在两个进程中看到这一点。
add fflush(stdout);after printf()and try.
添加fflush(stdout);后printf()尝试。

