fork() 函数在 if 语句中的行为如何?
How does the fork() function behave in if statements?
这里的 fork() 调用如何工作?我试图使用打印语句来理解它,但我对它感到更加困惑。我知道 !fork() 检查它是否是子进程意味着 fork()==0 & if (fork()) 意味着它是否是父进程。我不明白我们是如何得到这个输出的。如果有人能给出解释,这将消除我对 if 语句中 fork 调用的疑虑。
#include <stdio.h>
#include <unistd.h>
static int x = 0;
int main(int argc, char *argv[])
{
pid_t p = getpid();
x++;
fork();
if (!fork())
{
if (fork())
{
x++;
}
x++;
}
printf("p%d: x = %d\n", getpid() - p, x);
sleep(60);
return 0;
}
输出:
p0: x = 1
p1: x = 1
p2: x = 3
p4: x = 2
p3: x = 3
p5: x = 2
关于你的问题,输出是如何实现的?
以下讨论假设fork()
总是成功
fork();
// now have both parent and child processes
if (!fork())
// total of 4 processes
// now have a parent and a child process for each of the prior parent and child process
// but only the two child processes are executing inside this `if` body
{
if (fork())
// now have 6 processes
// now have another parent and child process for each of the prior processes
// but only the two new parent processes are executing inside this `if` body
{
x++;
}
您需要更多详细信息吗?
执行第一个 fork();
调用后,您现在有两个进程 运行。
执行 if (!fork())
后,您现在有四个进程(因为前两个已分叉)。但是,if 条件的主体只会在其中两个(子进程)中执行。这意味着 x
将在 if 条件的主体内仅在两个过程中递增。
然后,在执行 if (fork())
之后,这两个子进程将自己分叉,这意味着您现在总共有六个进程。但是 x
仅在两个父进程中递增,在这两个进程中赋予它最终值 3。
别想if
中的fork()
调用,想什么fork()
确实如此。
fork()
是一个函数,它 通过复制
调用进程(参见man 2 fork
)。这意味着当您调用 fork()
并假设调用没有失败,那么你将有两个进程,
原始过程和一个新过程,即原始过程的副本。做什么
"copy" 是什么意思?表示内存和进程恢复的点
工作是一样的(实际上是复制意味着更多,但我尽量保持它
简单)。
现在有 2 个进程,它们都在同一点恢复工作。
但它们在一个关键点上有所不同:fork()
调用的 return 值:
- parent(又名原始)获取分叉进程的 pid
- child(又名副本)从分叉进程中获取 0
这是区分 parent 和 child 的唯一方法。所以当你工作时
对于 fork
,您应该使用此模式:
pid_t pid = fork();
if (pid < 0)
{
// ABORT, ERROR
// no processes created
}
if(pid == 0)
{
// CHILD PROCESS
} else {
// PARENT PROCESS
// at some point, parent needs to wait for the child
waitpid(pid, NULL, 0); // see man 2 waitpid for more info on that
}
那么,让我们看一下您的代码:
- 第一个
fork()
x
的值是1。两个进程都保持运行。
让我们调用 parent 进程 A
和 child 进程 B
.
- 在第二个
fork()
A
和 B
生成新进程,让我们忘记
他们一秒钟。在 A
的情况下,第二个 fork()
returns 的 pid
下一个过程(C
、child of A
)并且由于 !
表达式的计算结果为 0,因此
inner inner 语句不会为 A
执行,它会跳转到打印 1. 的 printf
行
- 这同样适用于
B
,因为它是 A
. 的副本
- 现在让我们考虑第二个
fork()
。
- 我们知道
A
会生成第二个 child、C
。我们知道 A
发生了什么
然后。但是 fork()
在 C
中调用 returns 0,所以 !
将其评估为 1
并执行内部 if
语句。
- 现在它再次调用
fork()
,这里 C
产生 D
但 C 的 fork()
调用得到
D
的 pid,if 计算结果为真并执行 x++
之后
再次 x++
。所以当它最终打印出 x 的值时,你得到 3。因为我们
说的是C
,A
的grandchild,getpid() - p
是2.
- 等等
我不会继续解开 fork()
调用,但现在你知道怎么做了
fork()
乖乖,拿笔和纸继续做。
您会看到打印件中的值匹配。
编辑:
我建议您阅读 fork()
的手册页。打开终端并输入
man 2 fork
它更详细地解释了 fork()
的工作原理以及副本的含义。
您还应该阅读 waitpid
的手册页。你需要调用它,除非
你想要僵尸进程。
这里的 fork() 调用如何工作?我试图使用打印语句来理解它,但我对它感到更加困惑。我知道 !fork() 检查它是否是子进程意味着 fork()==0 & if (fork()) 意味着它是否是父进程。我不明白我们是如何得到这个输出的。如果有人能给出解释,这将消除我对 if 语句中 fork 调用的疑虑。
#include <stdio.h>
#include <unistd.h>
static int x = 0;
int main(int argc, char *argv[])
{
pid_t p = getpid();
x++;
fork();
if (!fork())
{
if (fork())
{
x++;
}
x++;
}
printf("p%d: x = %d\n", getpid() - p, x);
sleep(60);
return 0;
}
输出:
p0: x = 1
p1: x = 1
p2: x = 3
p4: x = 2
p3: x = 3
p5: x = 2
关于你的问题,输出是如何实现的?
以下讨论假设fork()
总是成功
fork();
// now have both parent and child processes
if (!fork())
// total of 4 processes
// now have a parent and a child process for each of the prior parent and child process
// but only the two child processes are executing inside this `if` body
{
if (fork())
// now have 6 processes
// now have another parent and child process for each of the prior processes
// but only the two new parent processes are executing inside this `if` body
{
x++;
}
您需要更多详细信息吗?
执行第一个 fork();
调用后,您现在有两个进程 运行。
执行 if (!fork())
后,您现在有四个进程(因为前两个已分叉)。但是,if 条件的主体只会在其中两个(子进程)中执行。这意味着 x
将在 if 条件的主体内仅在两个过程中递增。
然后,在执行 if (fork())
之后,这两个子进程将自己分叉,这意味着您现在总共有六个进程。但是 x
仅在两个父进程中递增,在这两个进程中赋予它最终值 3。
别想if
中的fork()
调用,想什么fork()
确实如此。
fork()
是一个函数,它 通过复制
调用进程(参见man 2 fork
)。这意味着当您调用 fork()
并假设调用没有失败,那么你将有两个进程,
原始过程和一个新过程,即原始过程的副本。做什么
"copy" 是什么意思?表示内存和进程恢复的点
工作是一样的(实际上是复制意味着更多,但我尽量保持它
简单)。
现在有 2 个进程,它们都在同一点恢复工作。
但它们在一个关键点上有所不同:fork()
调用的 return 值:
- parent(又名原始)获取分叉进程的 pid
- child(又名副本)从分叉进程中获取 0
这是区分 parent 和 child 的唯一方法。所以当你工作时
对于 fork
,您应该使用此模式:
pid_t pid = fork();
if (pid < 0)
{
// ABORT, ERROR
// no processes created
}
if(pid == 0)
{
// CHILD PROCESS
} else {
// PARENT PROCESS
// at some point, parent needs to wait for the child
waitpid(pid, NULL, 0); // see man 2 waitpid for more info on that
}
那么,让我们看一下您的代码:
- 第一个
fork()
x
的值是1。两个进程都保持运行。 让我们调用 parent 进程A
和 child 进程B
. - 在第二个
fork()
A
和B
生成新进程,让我们忘记 他们一秒钟。在A
的情况下,第二个fork()
returns 的 pid 下一个过程(C
、child ofA
)并且由于!
表达式的计算结果为 0,因此 inner inner 语句不会为A
执行,它会跳转到打印 1. 的 - 这同样适用于
B
,因为它是A
. 的副本
- 现在让我们考虑第二个
fork()
。 - 我们知道
A
会生成第二个 child、C
。我们知道A
发生了什么 然后。但是fork()
在C
中调用 returns 0,所以!
将其评估为 1 并执行内部if
语句。 - 现在它再次调用
fork()
,这里C
产生D
但 C 的fork()
调用得到D
的 pid,if 计算结果为真并执行x++
之后 再次x++
。所以当它最终打印出 x 的值时,你得到 3。因为我们 说的是C
,A
的grandchild,getpid() - p
是2. - 等等
printf
行
我不会继续解开 fork()
调用,但现在你知道怎么做了
fork()
乖乖,拿笔和纸继续做。
您会看到打印件中的值匹配。
编辑:
我建议您阅读 fork()
的手册页。打开终端并输入
man 2 fork
它更详细地解释了 fork()
的工作原理以及副本的含义。
您还应该阅读 waitpid
的手册页。你需要调用它,除非
你想要僵尸进程。