1

I need some help with programming in C, I have a question which wants me to create some arbitrary number of child processes, each of which executes a child process function. The number of child processes is supposed to be supplied as a command line argument, and in the child process function it should run a random number of iterations through a simple loop then print "Child X" where X is provided as an argument. If anyone could help guide me through this that would be awesome!

I tried this but I don't understand how processes work in C.

Amended code

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

int main(int argc, char **argv) {

  int counter;
  pid_t pid = getpid();
  int x = atoi(argv[1]);  // Changed (added)

  printf("Parent Process, my PID is %d\n", pid);

  for(counter=1;counter <= x;counter++){  // Changed
    if(!fork()){
      printf("Child %d is born, my PID is %d\n", counter, getpid());  // Changed
      childprocess(counter);
      printf("Child %d dies\n", counter);
      exit(0);
    }
  }
}

void childprocess(int num){
  int i = 1;

  while(i <= num){
    printf("Child %d executes iteration: %d\n", num, i);  // Changed
    i++;
  }

}

Original code

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

    int main(int argc, char **argv) {

      int counter;
      pid_t pid = getpid();

      printf("Parent Process, my PID is %d\n", pid);

      for(counter=1;counter <= argv[1];counter++){
        if(!fork()){
          printf("Child %d is born, my PID is %d\n", counter, pid);
          childprocess(counter);
          printf("Child %d dies\n", counter);
          exit(0);
        }
      }
    }

    void childprocess(int num){
      int i = 1;

      while(i <= num){
        printf("Child %d executes iteration: %d\n", i);
        i++;
      }

    }
Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
datasplice
  • 494
  • 1
  • 3
  • 16
  • 1
    `argv[1]` is a string; you have to convert it to an integer. You also need to think about how you create random numbers — there is no randomization in your code. Beware — unless each process sets the seed to a unique value, you will get the same sequence of random numbers from each child. Why not use a `for` loop instead of a `while` loop in `childprocess()`? Your `printf("Child %d executes iteration: %d\n", i);` is wrong — you have two `%` conversion specifications and just one argument. – Jonathan Leffler Oct 02 '19 at 00:48
  • @JonathanLeffler thanks for pointing out my errors! I've converted the string to an integer and I've added the second argument to the printf() as well. Is this creating child processes the way I described? I've never done something like this before and I'll be sure to keep the random number thing in mind. Currently I get the error "line 5: syntax error near unexpected token `(' " – datasplice Oct 02 '19 at 01:08
  • 1
    In the code shown in the question, line 5 is the `int main(int argc, char **argv) {` line. It is not remotely clear why that would generate a syntax error — you've got to be trying rather hard to get that. Check that you're compiling the source you have been editing. [user3062014](https://stackoverflow.com/users/3062014/user3062014) correctly points out that you've not use `getpid()` enough. For the randomization, it's probably sufficient to use the child PID to initialize `srand()` — you can then use `rand()` to generate distinct numbers. Think about using `rand() % 100` to limit the loops. – Jonathan Leffler Oct 02 '19 at 01:14
  • 1
    Be wary of making changes to your question that make any answers irrelevant. In this context, probably you could have the original code (to make the answer relevant again; it doesn't matter much about the comments) and the revised code. If your program is bigger, it gets trickier. I've done it for you this time — please remember for the future. – Jonathan Leffler Oct 02 '19 at 01:17
  • @JonathanLeffler I appreciate the advice on that! I thought it might make things clearer but that makes sense! Could it maybe be that I've declared the function 'childprocess' to be void where it shouldn't be? I see I had thought that setting 'pid_t pid = getpid()' and then using that would work. Thank you for the help on this! – datasplice Oct 02 '19 at 01:24
  • 1
    I have hacked the modified code a bit, adding the function declaration before `main()`. The return type of `void` is fine; it doesn't have a value to return. I added code to initialize random numbers (`srand()` — see [`srand()` — why call it only once?](https://stackoverflow.com/questions/7343833/srand-why-call-it-only-once/) and realize that its rule doesn't apply to your code if you want the children to behave differently from each other), and then do a random number of iterations (I used `int max = srand() % 100;` so I didn't have millions of iterations printing). It works OK with that. – Jonathan Leffler Oct 02 '19 at 01:31
  • 1
    I also checked that `argv[1]` was provided — producing a usage message if not. – Jonathan Leffler Oct 02 '19 at 01:32

2 Answers2

3

The pid value is always that of the parent. It would fork, but print out the same number. Try:

printf("Child %d is born, my PID is %d\n", counter, getpid());

to get the child's PID after the fork. The printf("Child %d executes iteration: %d\n", i); bit has 2 %, but only one value. Try

printf("Child %d executes iteration: %d\n", num, i);
user3062014
  • 136
  • 1
  • 4
2

Here's a simple adaptation of the 'Amended Code' (as of revision 4):

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

void childprocess(int num);

int main(int argc, char **argv)
{
    if (argc != 2)
    {
        fprintf(stderr, "Usage: %s num-procs\n", argv[0]);
        exit(EXIT_FAILURE);
    }
    int counter;
    pid_t pid = getpid();
    int x = atoi(argv[1]);

    printf("Parent Process, my PID is %d\n", pid);

    for (counter = 1; counter <= x; counter++)
    {
        if (!fork())
        {
            printf("Child %d is born, my PID is %d\n", counter, getpid());
            childprocess(counter);
            printf("Child %d dies\n", counter);
            exit(0);
        }
    }
}

void childprocess(int num)
{
    srand(getpid());
    int max = rand() % 100;

    for (int i = 0; i < max; i++)
    {
        printf("Child %d executes iteration: %d\n", num, i);
    }
}

Sample output (program procs13 compiled from procs13.c):

$ procs13 3
Parent Process, my PID is 23487
Child 1 is born, my PID is 23488
Child 1 executes iteration: 0
Child 1 executes iteration: 1
Child 1 executes iteration: 2
Child 1 executes iteration: 3
Child 1 executes iteration: 4
Child 1 executes iteration: 5
Child 1 executes iteration: 6
Child 1 executes iteration: 7
Child 1 executes iteration: 8
Child 1 executes iteration: 9
Child 1 executes iteration: 10
Child 1 executes iteration: 11
Child 1 executes iteration: 12
Child 1 executes iteration: 13
Child 1 executes iteration: 14
Child 1 executes iteration: 15
Child 1 dies
Child 2 is born, my PID is 23489
Child 2 executes iteration: 0
Child 2 executes iteration: 1
Child 2 executes iteration: 2
Child 2 executes iteration: 3
Child 2 executes iteration: 4
Child 2 executes iteration: 5
Child 2 executes iteration: 6
Child 2 executes iteration: 7
Child 2 executes iteration: 8
Child 2 executes iteration: 9
Child 2 executes iteration: 10
Child 2 executes iteration: 11
Child 2 executes iteration: 12
Child 2 executes iteration: 13
Child 2 executes iteration: 14
Child 2 executes iteration: 15
Child 2 executes iteration: 16
Child 2 executes iteration: 17
Child 2 executes iteration: 18
Child 2 executes iteration: 19
Child 2 executes iteration: 20
Child 2 executes iteration: 21
Child 2 executes iteration: 22
Child 2 dies
Child 3 is born, my PID is 23490
Child 3 executes iteration: 0
Child 3 executes iteration: 1
Child 3 executes iteration: 2
Child 3 executes iteration: 3
Child 3 executes iteration: 4
Child 3 executes iteration: 5
Child 3 executes iteration: 6
Child 3 executes iteration: 7
Child 3 executes iteration: 8
Child 3 executes iteration: 9
Child 3 executes iteration: 10
Child 3 executes iteration: 11
Child 3 executes iteration: 12
Child 3 executes iteration: 13
Child 3 executes iteration: 14
Child 3 executes iteration: 15
Child 3 executes iteration: 16
Child 3 executes iteration: 17
Child 3 executes iteration: 18
Child 3 executes iteration: 19
Child 3 executes iteration: 20
Child 3 executes iteration: 21
Child 3 executes iteration: 22
Child 3 executes iteration: 23
Child 3 executes iteration: 24
Child 3 executes iteration: 25
Child 3 executes iteration: 26
Child 3 executes iteration: 27
Child 3 executes iteration: 28
Child 3 executes iteration: 29
Child 3 dies
$

I'm a little surprised that there is no concurrency shown, but that's how it worked on my Mac running macOS Mojave 10.14.6. Larger numbers in the iterations would probably give interleaved execution of the child processes. The parent process should probably use wait() or waitpid() to wait for the children to die.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
  • I also forgot the function declaration which would've caused more issues so thank you for pointing that out, I see how srand() works with the code from the link you provided! My code required quite a few tweaks but I at least feel I was on the right track! This makes sense to me now thank you so much for your help! – datasplice Oct 02 '19 at 01:46