Search code examples
clinuxunixforkposix

How many processes will be created


I have this piece of code and was wondering how many processes will be created. I am uncertain as I think because of the loop it will be 12 processes but also could be 8.

#include <unistd.h>
#include <sys/types.h>

int main() {
  pid_t childpid;
  int i;

  childpid = fork();

  for (i = 0; i < 3 && childpid == 0; i++) {

    if (childpid == -1) {
      perror("Failed to fork.");
      return 1;
    }

    fprintf(stderr, "A\n");

    childpid = fork();

    if (childpid == 0) {
      fprintf(stderr, "B\n");
      childpid = fork();
      fprintf(stderr, "C\n");
    }

  }

  return 0;
}

Solution

  • Yes, you can use aptitude to evaluate how many processes are created, but I let the program decide it for me.

    The child and parent are synchronized using semaphore, and a pcount variable is used to keep track of the number of created processes. pcount is incremented whenever childpid is evaluated to zero. Below are the additions to your program.

    #include <semaphore.h>
    #include <stdio.h>
    #include <errno.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <sys/mman.h>
    
    int main(void)
    {
        /* Initialize and setup a semaphore */
    
        sem_t* sema = mmap(NULL, sizeof(sem_t), PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0);
    
        if (sema == MAP_FAILED)
            exit(1);
    
        if (sem_init(sema, 1, 1) != 0)
            exit(1);
    
        /* Initialize pcount */
    
        int* pcount = mmap(NULL, sizeof(int), PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0);
    
        if (pcount == MAP_FAILED)
            exit(1);
    
        *pcount = 1;
    
        printf("pcount = %d\n", *pcount);
    
        pid_t childpid;
        int i;
    
        childpid = fork();
    
        if (childpid == 0) {
            sem_wait(sema);
            *pcount = *pcount + 1;
            printf("pcount = %d\n", *pcount);
            sem_post(sema);
        }
    
        for (i = 0; i < 3 && childpid == 0; i++) {
    
            if (childpid == -1) {
                perror("Failed to fork.");
                return 1;
            }
    
            fprintf(stderr, "A\n");
    
            childpid = fork();
    
            if (childpid == 0) {
    
                sem_wait(sema);
                *pcount = *pcount + 1;
                printf("pcount = %d\n", *pcount);
                sem_post(sema);
    
                fprintf(stderr, "B\n");
                childpid = fork();
    
                if (childpid == 0) {
                    sem_wait(sema);
                    *pcount = *pcount + 1;
                    printf("pcount = %d\n", *pcount);
                    sem_post(sema);
                }
    
                fprintf(stderr, "C\n");
            }
        }
    
        return 0;
    }
    

    Terminal Session:

    $ gcc SO.c -lpthread 
    $ ./a.out
    pcount = 1
    pcount = 2
    A
    pcount = 3
    B
    C
    pcount = 4
    C
    A
    pcount = 5
    B
    C
    pcount = 6
    C
    A
    pcount = 7
    B
    C
    pcount = 8
    C
    

    So yes, 8 is the answer. Easy-Peasy :)