2

For an assignment, I'm supposed to create four processes in total, and print a letter multiple with each process. I'm supposed to call fork() twice to accomplish this.

I've been able to print the letters multiple times for each process. The problem arises in the second part of the assignment details. I'm supposed to print out the process ID for each process running before I print out the letters. The output should look like this:

Process ID: 123
Process ID: 124
Process ID: 125
Process ID: 126
AAAAABBBBBCCCCCDDDDD

I thought this could be accomplished by using this code:

pid_t child1, child2;
child1 = fork();
child2 = fork();

printf("Process created. ID: %d\n", getpid());

if(child1 == 0) { // print letters }
else if(child2 == 0) { //print letters }
else { // call waitpid and print more letters }

I thought since fork() splits at line child1 = fork(), then splits again at child2 = fork(), then goes to the next line, it would print everything out then hit the if-else statements. However, this is my output:

Process created. ID: 20105
Process created. ID: 20107
AAProcess created. ID: 20106
AAABBBProcess created. ID: 20108
BBCCCCCDDDDD

How can I ensure that my Process Created print statements execute first?

Alex
  • 2,145
  • 6
  • 36
  • 72
  • I'm confused here ` child1 = fork(); child2 = fork();` if I'm correct this will create child process within child .. An I beleive it's not what you want – Kavindu Dodanduwa Feb 05 '15 at 08:33
  • Have you tried to add a delay after your print id statement? such as [`sleep`](http://man7.org/linux/man-pages/man3/sleep.3.html) so the print letters will be printed after the id has been printed. – SSC Feb 05 '15 at 08:35
  • @SCC delay won't help I think Alex need to structure fork() well – Kavindu Dodanduwa Feb 05 '15 at 08:36
  • I am not sure with this statement `child2 = fork();` This statement will executed by the both first child and parent process. – Karthikeyan.R.S Feb 05 '15 at 08:44
  • @Karthikeyan.R.S I'm trying to create 4 processes total. How would I structure `fork()` differently to accomplish this? – Alex Feb 05 '15 at 08:51
  • 1
    @Alex - you need use fork after returning to parent :) – Kavindu Dodanduwa Feb 05 '15 at 08:52
  • After the parent process came to execution you create the one fork for third process. then in child block create another fork for fourth process. or else both in parent or both in child – Karthikeyan.R.S Feb 05 '15 at 08:53
  • 1
    @KCdod OP's purpose is to create 4 processes, `child1 = fork(); child2 = fork();` indeed does that. I really don't see what's wrong with it. Can you elaborate why OP needs to structure the `fork()` call? – SSC Feb 05 '15 at 08:54
  • @SSC `sleep(1)` actually works fine! Although is calling `fork()` in the way I've done it bad? – Alex Feb 05 '15 at 08:57
  • @SCC Sleep is not the solution. And i know it create 4 processes but second fork is executed by first created child and also by main process. Which is not the solution i think he really need . Also rather than Sleep he need to use wait() that's what I refer with restructuring – Kavindu Dodanduwa Feb 05 '15 at 09:02
  • @Alex KCdod is right, `sleep()` is a wrong way to do it if you need the letters to print in order. – SSC Feb 05 '15 at 09:07
  • 1
    @SSC I do not need the letters to print in order. In fact, randomization is encouraged for the assignment. But after testing it some more.. child1 prints out twice.. so I probably should restructure the `fork()` – Alex Feb 05 '15 at 09:11
  • @KCdod Yeah you called it with a fork being executed twice. I'll take a look at your solution and try to implement it. Thank you :) – Alex Feb 05 '15 at 09:15
  • 1
    Taking this "*I'm supposed to call fork() **twice** to accomplish this.*" literally you will be able to create two (additional) processes, that is one by each call to`fork()`. So your assigment to "*to create **four** processes in total*" is not feasable. – alk Feb 05 '15 at 09:30
  • Try looking at it like this: Printing the PID is a "post-creation" action, whereas printing letters is a "pre-termination" action. – alk Feb 05 '15 at 09:44
  • Also you surely noticed that there is a "synchronisation" issue with the shared resource `stdout`. Hint: To synchronise one needs something that "waits" for something else to "happen". – alk Feb 05 '15 at 09:48
  • @alk I did notice that. Do I use nested if-else-if statements like in the answer below? And print the PID after each fork? Then wait until its done to print out my `child1`,`child2`, and `child3` letters? If I don't use the if-else-if system, how do I accomplish it? – Alex Feb 05 '15 at 09:52

2 Answers2

0
child1 = fork(); // Fork 1 here 
child2 = fork(); // Fork 2 here after first fork .!!

Above fork will true that create four processes. But you are doing the second fork() with original parent and also by your first child. I guess this is not what you really need to do. You need to start three processes only with original parent.

Look at the given example : Here I create 2 child processes and all process count is 3 [With main] . Here I have tried to provide a reference solution with required output.

#include <unistd.h>     /* Symbolic Constants */
#include <sys/types.h>  /* Primitive System Data Types */ 
#include <stdio.h>      /* Input/Output */
#include <sys/wait.h>   /* Wait for Process Termination */
#include <stdlib.h>     /* General Utilities */

int main()
{
    pid_t childpid1,childpid2; /* variable to store the child's pid */

    /* now create new process */
    childpid1 = fork();

    if (childpid1 >= 0) /* fork succeeded */
    {
        if (childpid1 == 0) /* fork() returns 0 to the child process */
        {
            printf("1 : %d \n",getpid());

            printf("AA");    
        } 
        else /* fork() returns new pid to the parent process */
        {
             childpid2 = fork();
             if (childpid2 >= 0) /* fork succeeded */
             {
                  if (childpid2 == 0) /* fork() returns 0 to the child process */
                  {
                  printf("2 :%d \n",getpid());

                  int stat;
                  waitpid(childpid1, &stat, 0);

                  printf("BB");    
                  } 
                  else /* fork() returns new pid to the parent process */
                  {
                    printf("3 : %d \n",getpid()); // This is the Original parent of ALL

                    int stat2;
                    waitpid(childpid2, &stat2, 0);

                    printf("CC");             
                  }
             }
        }
    }

    return 0;
}
Kavindu Dodanduwa
  • 12,193
  • 3
  • 33
  • 46
  • 1
    Unfortunately, this ends up printing the parent ID, the child1 ID, then prints "AA", then prints child 2 ID, then prints "BB", then prints child 3 id, and then prints "CC" Is there a way to wait until the first print statements have started before printing out AA, BB, and CC? – Alex Feb 05 '15 at 09:37
-1

You have a synchronisation problem here: multiple processes share single resource (stdout) and are trying to print to it. You have two possible solutions here: either make your main process manager of the resource and make child processes send desired output to it (for example with pipes, this answer can give you a hint how to do it), or you need to use synchronisation with semaphores (here is a very good example).

Community
  • 1
  • 1
iwlagn
  • 477
  • 3
  • 10
  • You miss the 3rd option, which is sequentialising the calls to `printf()` by properly combining/"synchronising" the different processes' calls to `fork()` and `wait()`. – alk Feb 05 '15 at 09:40
  • I would not agree that in general use of ´wait()´ is a good idea. It might be a solution for some cases, but here, since you need to synchronise 4 processes, one would need to put to much effort to obtain correct values for ´wait()´ comparing to use of semaphores. – iwlagn Feb 05 '15 at 10:06