C 进程 fork()
我正在探索父进程& UNIX 中的子进程概念。我写了这段小代码,认为 x 不。或者会创建流程。但它创建了一个不同的数字 -
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
int main(int argv, char *argc[])
{
int i;
pid_t childpid;
for(i=0; i<3; i++)
{
childpid = fork();
if(childpid == -1)
{
perror("Failed to Fork");
return 1;
}
if(childpid == 0)
printf("You are in Child: %ld\n", (long)getpid());
else
printf("You are in Parent: %ld\n", (long)getpid());
}
return 0;
}
OUTPUT:
You are in Parent: 30410
You are in Child: 30411
You are in Parent: 30410
You are in Child: 30412
You are in Parent: 30411
You are in Parent: 30410
You are in Child: 30413
You are in Child: 30414
You are in Parent: 30412
You are in Parent: 30411
You are in Child: 30415
You are in Child: 30416
You are in Parent: 30413
You are in Child: 30417
我知道在 fork() 情况下,父级或子级可能会在执行中获得优先权。这并不困扰我,困扰我的是正在执行的进程数量。为什么是14?而不是执行 fork() 时会发生的某个 2^n 数字;叉(); fork() 即 fork 一个接着一个。
我缺少什么?
更新:还有一项澄清 -
fork
函数复制父级 内存映像以便新进程 接收地址空间的副本 父母的。
这意味着什么?这是否意味着
- 子进程在 fork() 语句之后开始执行?
- 子进程获取父进程变量的副本?那么如果
x=3
高于fork,子进程会看到这个x为3吗?
I am exploring parent process & child processes concept in UNIX. I wrote this small code thinking that x no. or processes would get created. But it has created a different number -
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
int main(int argv, char *argc[])
{
int i;
pid_t childpid;
for(i=0; i<3; i++)
{
childpid = fork();
if(childpid == -1)
{
perror("Failed to Fork");
return 1;
}
if(childpid == 0)
printf("You are in Child: %ld\n", (long)getpid());
else
printf("You are in Parent: %ld\n", (long)getpid());
}
return 0;
}
OUTPUT:
You are in Parent: 30410
You are in Child: 30411
You are in Parent: 30410
You are in Child: 30412
You are in Parent: 30411
You are in Parent: 30410
You are in Child: 30413
You are in Child: 30414
You are in Parent: 30412
You are in Parent: 30411
You are in Child: 30415
You are in Child: 30416
You are in Parent: 30413
You are in Child: 30417
I understand that in a fork()
situation a parent or a child might get preference in execution. That's is not bothering me, what's bothering me is the number of processes that are getting executed. Why is it 14? and not some 2^n number which is what would happen if we are executing fork(); fork(); fork()
i.e. fork's one after the other.
What am I missing?
UPDATE: One more clarification -
The
fork
function copies the parent
memory image so that the new process
receives a copy of the address space
of the parent.
What does this mean? Does it mean -
- the child process starts executing after the
fork()
statement? - the child process gets a copy of the parent process variables? so if
x=3
above fork, will the child process see this x as 3?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
您有 8 个进程正在执行,只是其中一些进程由于循环而多次打印。
如果对输出进行排序:
那么您可以看到只有 8 个唯一的进程 ID。
其原因很微妙。因为子进程(几乎)继承了父进程的所有内容,所以它也获取循环的当前状态。我说“几乎”是因为某些东西是不同的,例如 PID(显然)、父 PID(同样明显)和某些资源限制(取决于操作系统)。
因此,当
i == 0
分叉成两个时,处理0。两者的下一个周期都在i == 1
处。这两个都将在i == 2
处分叉下一个周期。等等。如果您检查下图,您可以看到创建过程。
/
、|
和\
行表示i
为0
处的分叉>、1
和2
分别。请注意,从
i == 1
的父进程创建的进程(例如E
)只会使用i == 2
进行分叉。换句话说,它是用|
创建的,因此下一步是\
。类似地,使用
/
(i == 0
) 创建的B
将仅使用|
(<代码>i == 1)和\
(i == 2
)。如果您对 fork 的其他信息感兴趣,请参阅我的长篇文章此处,以及有关 Linux 下不同 fork 选项内部结构的一些详细信息 这里。
You have 8 processes there being executed, it's just that some of them are printing more than once because of the loop.
If you sort the output:
then you can see that there are only 8 unique process IDs.
The reason for this is subtle. Because a child process inherits (almost) everything from the parent, it gets the current state of the loop as well. I say "almost" since certain things are different, such as the PID (obviously), parent PID (equally obviously) and certain resource limits (depending on the OS).
So, process 0 when
i == 0
forks into two. both with their next cycle ati == 1
. Both of these will fork with their next cycle ati == 2
. And so on.If you examine the following diagram, you can see the creation process.
The lines
/
,|
and\
represent forks at the points wherei
is0
,1
and2
respectively.Note that a process (such as
E
) which was created from a parent wherei == 1
will only fork withi == 2
. In other words, it was created with|
so its next step is\
.Similarly,
B
that was created with/
(i == 0
) will then only fork with|
(i == 1
) and\
(i == 2
).If you're interested in other information on fork, see my voluminous essay here, and some details on the internals of different fork options under Linux here.
当您调用 fork() 时,程序将在处理期间的位置准确启动。所以你有
i=0,2 个进程
i=1, 4 个进程
i=2, 8 个进程
,正如 rlibby 在他的评论中指出的那样,我忘记考虑以下事实:每一次原始通过都是总数的一部分。所以我的数学是错误的。应该是:
i=0,1个进程+1个新进程(总共2个)
i=1, 2 个进程 + 2 个新进程(总共 4 个)
i=2,4个进程+4个新进程(总共8个)
When you call fork(), the program starts EXACTLY where it was during processing. So you have
i=0, 2 processes
i=1, 4 processes
i=2, 8 processes
as rlibby pointed out in his comment, I forgot to take into account the fact that the processes from each of the original passes are part of the totals. So my math was wrong. It should be:
i=0, 1 process + 1 new (2 total)
i=1, 2 processes + 2 new (4 total)
i=2, 4 processes + 4 new (8 total)
我认为您看到创建如此多进程的原因是,当您
fork
子进程时,它位于for
循环的中间。因此,在打印出它是一个子级之后,它将继续循环并分叉自己的子级。要解决此问题,只需让子级在打印出它们是子级后退出即可:
顺便说一句,这确实解释了为什么您会看到一个循环有 2n 个进程进行 n 次迭代。在每次迭代中,每个进程都会分为两个进程,然后运行其余的循环迭代。这意味着每次迭代都会使进程数量加倍,因此在 n 次迭代之后,您将看到 2n 个进程。
希望这有帮助!
I think that the reason you're seeing so many processes get created is that when you
fork
a child process, it's in the middle of thefor
loop. Consequently, after it prints out that it's a child, it will then continue looping and forking its own children.To fix this, just have the children exit after printing that they're children:
By the way, this does explain why you're seeing 2n processes for a loop doing n iterations. On each iteration, each process splits into two processes that then run for the rest of the loop iterations. This means that each iteration doubles the number of processes, so after n iterations you'll see 2n processes.
Hope this helps!
只有8个进程。计算唯一进程 ID。
There are only 8 processes. Count the unique process IDs.
我认为添加一个中断而不是添加一个 exit(0) 也可以。
I think adding a break instead of adding an exit(0) would also work.