问叉()多个进程Unix

所以我有这个函数,分叉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 

fork()调用产生一个新进程,它 fork发生的完全相同的点开始执行。 所以,它看起来像是“两次返回”

这里发生的是fork()调用返回两次,因此父进程和子进程都继续循环并生成新进程。 每个孩子(原来的父母和孩子)然后再次分叉,反复加倍进程的数量……

当你fork一个进程时,你基本上得到了两个(几乎)精确的进程副本,并且它们都将继续运行。

所以正在发生的事情是,孩子们自己在自己的进程空间(在他们打印输出之后) 以及父进程中继续循环。 而且,事实上,因为这些孩子也在分叉,所以孙子孙女也将继续从那时起。 我确定有一个公式可以确定你最终有多少孩子(可能是N!)但我现在没有精力解决这个问题。 最好使用以下解决方案。

告诉父和子之间区别的方法是fork的返回值。

  • 如果你回到-1,那么你就是父,而fork失败了。
  • 如果你回到零,你就是孩子。
  • 如果你得到一个正数,你就是父,那个数字是子PID(所以你可以操纵它或wait它)。

这是一些测试代码:

 #include  #include  #include  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并继续迭代#2循环等。

分叉进程时,会生成当前进程的副本:生成的子进程在fork()调用后继续执行。 这就是你必须处理逻辑中的返回代码的原因。

在本练习中,我将使用递归而不是for循环。 这样,您可以多次调用fork()指令,但只能在进程的两个副本之一上执行。 你可以让子进程产生另一个子进程,因此有祖父母,曾祖父母等,或者你可以在父方调用fork(),只有一个“父”和多个子进程。 这是实现后一种解决方案的代码示例:

 #include  #include  #include  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 \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); } }