alteration
alteration

Reputation: 53

fork() created process don't execute in parallel

I got an integer matrix in shared memory with n colums, so I create n processes, each of them make the sum of a colum. The problem is that they don't execute in parallel. There is the code (this doesn't actually do the sum, was to test):

    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);

What I get is that it runs in this order process 3, 2, 1 and ends in the same order, always. But the sleep is random, so the arrival time should be random too! Also I don't understand why it starts from process 3.

Upvotes: 0

Views: 1759

Answers (2)

Jean-Baptiste Yun&#232;s
Jean-Baptiste Yun&#232;s

Reputation: 36391

Your code is wrong and don't do what you think.

In the case of fork() success, the caller increments i, and then the final test of the while is false, so the original process terminates. While the new process executes its code "start 0", "terminates 0", then jumps to the test which is true and then fork again, etc. So your processes are always produced one after the other in the same order.

Here is the corrected code (with random seeding):

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

Upvotes: 2

nsilent22
nsilent22

Reputation: 2863

When you don't seed random number generator with srandom function, you'll always get the same sequence of "random" numbers. Usually you seed it doing srandom(time(NULL)) call.

Check this simple program:

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

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

On my computer it always outputs 1804289383.

Also, when you call rand in your child process it always inherits parent's state of random-number-generating-machine, so your children will always generate the same random number. You shall generate this random number before forking. In the following code all children return the same random value:

#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;
}

Last thing is, creating some processes one-after-another doesn't mean they will get processor's time in that order. It's perfectly OK that when you fork your first child, processor's context will return to the parent, who will do another fork, and then processor's context will be assigned to the second child, not the first one.

Code that works:

#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;
}

Upvotes: 1

Related Questions