1

I want to create n child processes by fork () inside a for loop, and treat the child processes later once they have all been created.The child processes must be treated once the execution of the parent process has been carried out.

    int main(int argc, char *argv[])
{
    char cadena[STRLONG];

    pid_t pid;
    
    for(int i =0; i<5; i++){
        pid = fork();

        if(pid == -1){
            perror("Error\n");
            exit(-1);
        }
        else if(pid == 0){
            break;
        }
    }

    if (pid > 0){
        printf("I'm the parent, --> %d\n", getpid());
    }
    else if(pid == 0){
        printf("I'm the child --> %d \n", getpid());
        exit(0);
    }
    for(int i = 0; i<5; i++){
        wait(NULL);
    }
}

This is what I have done, but the child processes are executed before they are all created and I don't know how to solve it ...

Ted Lyngmo
  • 93,841
  • 5
  • 60
  • 108
angel.bn
  • 11
  • 1
  • 1
    fork will immediately start the child process. The only way to stall the execution is to add interprocess semaphore's or something similar and have the children wait on the semaphore. – Damian Dixon Oct 28 '21 at 09:52
  • Probably add the your program's output to the question and then explain why it is not behaving as you expect – doron Oct 28 '21 at 09:55
  • 2
    One option may be to create a single pipe inherited by all the children. The parent can write 5 bytes to the pipe (one byte per child) after it has finished forking all the children, and the children can block until they have read a single byte from the pipe before they do anything else. – Ian Abbott Oct 28 '21 at 09:58
  • 1
    @IanAbbott The old pipe trick. Nice! It's usually enough to just close the pipe though. – Ted Lyngmo Oct 28 '21 at 09:59
  • angel bn: If there's anything you'd like me to explain further in my answer, just ask and I'll try to make it clearer. – Ted Lyngmo Oct 28 '21 at 15:26

1 Answers1

4

When you fork(), the parent and child process will run in parallel immediately from the place where you fork().

time     parent      child
 |         |
 |         |
 |       fork()--------+
 |         |           |
 V         |           |    ​

There is no way of telling which one of them that does something before the other - unless you synchronize their actions in some way.

To do proper synchronization between processes you can use semaphores or some other interprocess communication technique. For this simple case, you could use the old self-pipe trick.

  • Create a pipe
  • When a child is created, close the writing end of the pipe in the child - and try reading a byte from the pipe. This will hang until there is a byte or the pipe is closed.
  • When all children have been created, close the reading end in the parent.
  • The state at this point should be:
    • The parent only has the write end of the pipe open.
    • All the children only have the read end of the pipe open, eagerly waiting for something to happen in the pipe.
  • When the parent want all the children to start working, close the write end of the pipe in the parent. This will cause the read operation in all the children to unblock.

There's no error checking in this below, but it'll show the idea:

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

enum { P_RD, P_WR }; // pipe indices, 0 and 1

int main() {
    pid_t pid;

    int pip[2];
    pipe(pip); // create a pipe from pip[P_WR] to pip[P_RD]

    for(int i = 0; i < 5; i++) {
        pid = fork();

        if(pid == -1) {
            perror("Error\n");
            exit(1);
        } else if(pid == 0) {
            close(pip[P_WR]);        // close write end of pipe
            char ch;                 // dummy buffer
            read(pip[P_RD], &ch, 1); // hang here until closed
            close(pip[P_RD]);        // close read end of pipe

            printf("I'm the child --> %d \n", getpid());
            exit(0);
        }
    }
    close(pip[P_RD]); // close read end of pipe

    // The state at this point:
    // * The parent only has the write end of the pipe open.
    // * All the children only have the read end of the pipe open.

    printf("I'm the parent --> %d\n", getpid());
    close(pip[P_WR]); // close write end of pipe to start children

    int wstatus;
    while((pid = wait(&wstatus)) != -1) {
        printf("%d died\n", pid);
    }
}
Ted Lyngmo
  • 93,841
  • 5
  • 60
  • 108