所以我有这个函数可以分配N个子进程。然而,似乎分叉超过指定。你能告诉我我做错了什么吗? 感谢
void forkChildren(int nChildren){
int i;
for(i = 1; i <= nChildren; i++){
pid = fork();
if(pid == 0)
printf("I'm a child: %d PID: %d\n",i, getpid());
}
}
主要是我打电话:
forkChildren(5);
我期待以下输出:
I'm a child: 1 PID: 2990
I'm a child: 2 PID: 2991
I'm a child: 3 PID: 2992
I'm a child: 4 PID: 2993
I'm a child: 5 PID: 2994
但我得到以下内容:
I'm a child: 1 PID: 2990
I'm a child: 2 PID: 2991
I'm a child: 3 PID: 2992
I'm a child: 4 PID: 2993
I'm a child: 5 PID: 2994
user@computer:~/directory/$ I'm a child: 2 PID: 2999
I'm a child: 3 PID: 3000
I'm a child: 3 PID: 3001
I'm a child: 4 PID: 3002
I'm a child: 5 PID: 3003
I'm a child: 5 PID: 3004
I'm a child: 4 PID: 3005
I'm a child: 5 PID: 3006
I'm a child: 4 PID: 3007
I'm a child: 5 PID: 3008
I'm a child: 3 PID: 3011
I'm a child: 4 PID: 3012
I'm a child: 4 PID: 3010
I'm a child: 5 PID: 3013
I'm a child: 5 PID: 3014
I'm a child: 5 PID: 3015
I'm a child: 4 PID: 3018
I'm a child: 5 PID: 3019
I'm a child: 5 PID: 3020
I'm a child: 5 PID: 3021
I'm a child: 5 PID: 3023
I'm a child: 5 PID: 3025
I'm a child: 5 PID: 3024
I'm a child: 4 PID: 3022
I'm a child: 5 PID: 3026
I'm a child: 5 PID: 3027
答案 0 :(得分:15)
当你fork
一个过程时,你基本上会得到两个(几乎)精确的过程副本,并且它们都会继续运行。
所发生的事情是,孩子们自己在自己的处理空间中继续循环(在他们打印输出之后)以及作为父母这样做。而且,事实上,因为这些孩子也在分叉,孙子孙女也将继续从那时起。我确定有一个公式可以确定你最终得到了多少孩子(可能是N!)但我现在没有精力解决这个问题。最好使用以下解决方案。
告诉父母和孩子之间差异的方法是fork
的返回值。
fork
失败了。wait
为它)。这是一些测试代码:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
void forkChildren (int nChildren) {
int i;
pid_t pid;
for (i = 1; i <= nChildren; i++) {
pid = fork();
if (pid == -1) {
/* error handling here, if needed */
return;
}
if (pid == 0) {
printf("I am a child: %d PID: %d\n",i, getpid());
sleep (5);
return;
}
}
}
int main (int argc, char *argv[]) {
if (argc < 2) {
forkChildren (2);
} else {
forkChildren (atoi (argv[1]));
}
return 0;
}
和一些输出显示正在发生的事情:
pax> forktest 5
I am a child: 1 PID: 4188
I am a child: 2 PID: 4180
I am a child: 3 PID: 5396
I am a child: 4 PID: 4316
I am a child: 5 PID: 4260
pax> _
答案 1 :(得分:14)
fork()调用产生一个新进程,该进程在发生fork的完全相同的点处开始执行。所以,看起来像fork“返回两次”
这里发生的是fork()调用返回两次,因此父进程和子进程都继续循环并生成新进程。然后每个孩子(原始父母和孩子)再次分叉,反复加倍进程数量......
答案 2 :(得分:1)
每个子进程都会启动并继续循环。
换句话说,生成子1并继续循环#2的迭代#。
当进程分叉时,会生成当前进程的副本:生成的子进程在fork()调用后继续执行。这就是你必须在逻辑中处理返回代码的原因。
答案 3 :(得分:1)
在本练习中,我将使用递归而不是for循环。这样,您可以多次调用fork()指令,但只能在该进程的两个副本之一上执行。你可以让子进程产生另一个子进程,因此有祖父母,曾祖父母等,或者你可以在父方调用fork(),只有一个“父”和多个子进程。这是实现后一种解决方案的代码示例:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int nChildren;
void myFork(int n);
int main(int argc, char *argv[]) {
// just a check on the number of arguments supplied
if (argc < 2) {
printf("Usage: forktest <number_of_children>\n");
printf("Example: forktest 5 - spawns 5 children processes\n");
return -1;
}
nChildren = atoi(argv[1]);
// starting the recursion...
myFork(nChildren-1);
return 0;
}
// the recursive function
void myFork(int n) {
pid_t pid;
pid = fork();
// the child does nothing but printing a message on screen
if (pid == 0) {
printf("I am a child: %d PID: %d\n", nChildren-n, getpid());
return;
}
// if pid != 0, we're in the parent
// let's print a message showing that the parent pid is always the same...
printf("It's always me (PID %d) spawning a new child (PID %d)\n", getpid(), pid);
// ...and wait for the child to terminate.
wait(pid);
// let's call ourself again, decreasing the counter, until it reaches 0.
if (n > 0) {
myFork(n-1);
}
}