user1985189
user1985189

Reputation: 669

using fork() to make 4 processes?

We were recently introduced to fork() in my applied OS design class, and I'm not understanding it very well. We need to use it to create four separate processes in C file, and then have three of these processes write to a named pipe, while the fourth reads from it.

This is the code I've tried so far:

// creating the named pipe
mknod("/tmp/namedpipe", S_IFIFO | 0600, 0);
int myPipe;

const char* colour;

pid_t p1, p2;

p1 = fork();
if (p1 < 0)
{
   printf("Fork failed\n");
}
else if (p1 == 0) // this is the child of p1, we'll call it "red"
{
   printf("\nPid %d %s", getpid(), "(red) started\n");
   myPipe = open("/tmp/namedpipe", O_WRONLY);
   colour = "RED\n";
   write(myPipe, colour, strlen(colour) +1);
   close(myPipe);
}
else // the is the parent of p1, we'll call it "green"
{
   printf("\nPid %d %s", getpid(), "(red) started\n");
   myPipe = open("/tmp/namedpipe", O_WRONLY);
   colour = "RED\n";
   write(myPipe, colour, strlen(colour) +1);
   close(myPipe);

   p2 = fork();
   if (p2 < 0)
   {
      printf("Fork failed\n");
   }
   else if (p2 == 0) // this is the child of p2, we'll call it "blue"
   {
      printf("\nPid %d %s", getpid(), "(blue) started\n");
      myPipe = open("/tmp/namedpipe", O_WRONLY);
      colour = "BLU\n";
      write(myPipe, colour, strlen(colour) +1);
      close(myPipe);
   }
   else // the is the parent of p2, we'll call it "reader"
   {
      printf("This is the reader process");
      myPipe = open("/tmp/namedpipe", O_RDONLY);
      char nextChar;
      while (read(myPipe, &nextChar, 1) == 1)
         printf("%c", nextChar);
      close(myPipe);
   }
}

This code seems to work fine if you comment out all the pipe-related statements, but otherwise it executes the first two print statements and then hangs, forcing a CTRL-C. I'm not sure if the problem lies in the forking or if it has to do with the way I'm writing and reading to the pipe. Please let me know.

Upvotes: 2

Views: 2950

Answers (2)

agbinfo
agbinfo

Reputation: 803

You open the pipe for writing. This will block until the pipe is opened for reading. Since the parent will not fork more child, it all stops.

I don't have access to a Unix platform so I didn't try to compile it but you can try something like this:

// creating the named pipe
#define CHILD_COUNT 3
mknod("/tmp/namedpipe", S_IFIFO | 0600, 0);
const char* childname[CHILD_COUNT] = { "Red", "Blue", "Yellow" };
const char* colorname[CHILD_COUNT] = { "RED\n", "BLUE\n", "YELLOW\n" };
int myPipe;

const char* colour;

pid_t p;
int i;
for (i=0; i<CHILD_COUNT; i++) 
{
  p = fork();
  if (p < 0) {
    printf("Fork failed\n");
  }
  else if (p == 0) // this is a child, do child stuff
  {
    printf("\nPid %d (%s) started\n", getpid(), childname[i]");
    myPipe = open("/tmp/namedpipe", O_WRONLY);
    colour = colorname[i]; // =="RED\n" for first child
    write(myPipe, colour, strlen(colour) +1);
    close(myPipe);
    return;
  }
  // else it's the parent, spawn more children
}

// Parent
printf("This is the reader process");
myPipe = open("/tmp/namedpipe", O_RDONLY);
char nextChar;
while (read(myPipe, &nextChar, 1) == 1)
    printf("%c", nextChar);
close(myPipe);

Upvotes: 2

user2404501
user2404501

Reputation:

Named pipe opens without O_NONBLOCK are synchronized among processes. If a process tries to open for writing, it will block until some other process attempts to open for reading. If the order is reversed, the reading process is blocked until the writing process attempts to open. Either way, both opens succeed at the same time.

In your program, you create a child process "red" which tries to open for writing, and a parent process "green" which also tries to open for writing. There's nobody reading yet, so both are blocked. The code that would create the other 2 processes isn't reached, because it comes after the open in the "green" process which is blocking it.

Upvotes: 4

Related Questions