fork() 创建的进程不并行执行

fork() created process don't execute in parallel

我在共享内存中得到了一个包含 n 列的整数矩阵,所以我创建了 n 个进程,每个进程都构成了一个列的总和。问题是它们不是并行执行的。有代码(这实际上并没有做总和,是为了测试):

    int pid2[n];
    i=0;
    do{
      pid2[i] = fork();
      if(pid2[i]==-1) printf("fork() fail!\n");
      else if(pid2[i]==0){
        printf("Start process %d \n", i);
        sleep((rand() % 50)/10);
        printf("Process %d terminated" ,i);
        }         
      else i++;
      }
    while(i<n&&pid2[i]>0);

我得到的是它始终按顺序进程 3、2、1 运行并以相同的顺序结束。但睡眠是随机的,所以到达时间也应该是随机的!我也不明白为什么它从进程3开始。

当您不使用 srandom 函数为随机数生成器播种时,您将始终获得相同的 "random" 数字序列。通常你播种它做 srandom(time(NULL)) 调用。

检查这个简单的程序:

#include <stdio.h>
#include <stdlib.h>

int main(void) {
    printf("%d\n", rand());
    return 0;
}

在我的电脑上它总是输出1804289383

此外,当您在 child 进程中调用 rand 时,它 总是 继承 parent 的 random-number-generating-machine 状态,因此您的 children 将 always 生成 相同的 随机数。你应该在分叉之前生成这个随机数。在下面的代码中所有 children return 相同的随机值:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>

#define CHILDREN 3

int main(void) {
    int i;
    for (i = 0; i < CHILDREN; ++i) {
        if (fork() == 0) {
            printf("rand is %d in child %d\n", rand(), i);
            return 0;
        }
        wait(NULL);
    }

    return 0;
}

最后一点是,创建一些进程 one-after-another 并不意味着它们将按顺序获得处理器的时间。完全可以,当你 fork 你的第一个 child 时,处理器的上下文将 return 到 parent,谁将执行另一个 fork,然后处理器的上下文将分配给第二个 child,而不是第一个。

有效代码:

#include <time.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>

#define CHILDREN 3
int main(void) {
    int pid, i, children = 0;
    srand(time(NULL));
    double sleeptime;
    for (i = 0; i < CHILDREN; ++i) {
        sleeptime = (rand() % 50) / 10.0;
        pid = fork();
        if (pid == -1) {
            perror("fork failed");
        } else if (pid == 0) {
            printf("Child %d crated\n", i);
            fflush(stdout);
            sleep(sleeptime);
            printf("Child %d terminated\n", i);
            fflush(stdout);
            return 0;
        } else {
            ++children;
        }
    }

    // wait for all childredn
    for (i  = 0; i < children; ++i) {
        wait(NULL);
    }

    return 0;
}

你的代码是错误的,不要按照你的想法去做。

fork()成功的情况下,调用者自增i,然后while最后的测试为false,所以原流程终止。当新进程执行它的代码 "start 0"、"terminates 0" 时,然后跳转到为真的测试,然后再次 fork 等等。所以你的进程总是以相同的顺序一个接一个地生成。

这是更正后的代码(随机播种):

int pid2[n];
i=0;
do{
  pid2[i] = fork();
  if(pid2[i]==-1) printf("fork() fail!\n");
  else if(pid2[i]==0){
    printf("Start process %d \n", i);
    sleep((rand() % 50)/10);
    printf("Process %d terminated" ,i);
    exit(0); // ends the child
    }         
  else i++;
  }
while(i<n&&pid2[i-1]>0); // test is last pid is correct