Still celebrating National IT Professionals Day with 3 months of free Premium Membership. Use Code ITDAY17

x
?
Solved

help on a ring problem.

Posted on 1998-05-02
7
Medium Priority
?
391 Views
Last Modified: 2013-12-26
Hi I am studying unix programming. However, I have difficulties to do one problem on a book(practical unix programming). There is no solutions provided in the book! I need to modify the following program to make it a bidirectinal ring so that the inormation can flow in either direction between neighbors on the ring.  

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
/*
 * Sample C program for generating a unidirectional ring of processes.
 * Invoke this program with a command-line argument indicating the
 * number of processes on the ring.  Communication is done via pipes
 * that connect the standard output of a process to the standard input
 * of its successor on the ring.  After the ring is created, each
 * process identifies itself with its process ID and the process ID
 * of its parent.  Each process then exits.
 */
 
void main(int argc,  char *argv[ ])
{
   int   i;             /* number of this process (starting with 1)   */
   int   childpid;      /* indicates process should spawn another     */
   int   nprocs;        /* total number of processes in ring          */
   int   fd[2];         /* file descriptors returned by pipe          */
   int   error;         /* return value from dup2 call                */
   int       status;
    /* check command line for a valid number of processes to generate */
   if ( (argc != 2) || ((nprocs = atoi (argv[1])) <= 0) ) {
       fprintf (stderr, "Usage: %s nprocs\n", argv[0]);
       exit(1);
   }
                        /* connect std input to std output via a pipe */
   if (pipe (fd) == -1) {
      perror("Could not create pipe");
      exit(1);
   }
   if ((dup2(fd[0], STDIN_FILENO) == -1) ||
       (dup2(fd[1], STDOUT_FILENO) == -1)) {
      perror("Could not dup pipes");
      exit(1);
   }
   if ((close(fd[0]) == -1) || (close(fd[1]) == -1)) {
      perror("Could not close extra descriptors");
      exit(1);
   }
        /* create the remaining processes with their connecting pipes */
   for (i = 1; i < nprocs;  i++) {
      if (pipe (fd) == -1) {
         fprintf(stderr,"Could not create pipe %d: %s\n",
            i, strerror(errno));
         exit(1);
      }  
      if ((childpid = fork()) == -1) {
         fprintf(stderr, "Could not create child %d: %s\n",
            i, strerror(errno));
         exit(1);
      }  
      if (childpid > 0)        /* for parent process, reassign stdout */
          error = dup2(fd[1], STDOUT_FILENO);
      else
          error = dup2(fd[0], STDIN_FILENO);
      if (error == -1) {
         fprintf(stderr, "Could not dup pipes for iteration %d: %s\n",
                 i, strerror(errno));
         exit(1);
      }  
      if ((close(fd[0]) == -1) || (close(fd[1]) == -1)) {
         fprintf(stderr, "Could not close extra descriptors %d: %s\n",
                i, strerror(errno));
         exit(1);
      }
      if (childpid)
         break;
   }

   wait(&status);
                                  /* say hello to the world */
   fprintf(stderr,"This is process %d with ID %d and parent id %d\n",
      i, (int)getpid(), (int)getppid());
   exit (0);
}     /* end of main program here */

0
Comment
Question by:pete_host
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 4
  • 2
7 Comments
 
LVL 1

Accepted Solution

by:
mrausch earned 500 total points
ID: 1292667
If you are running this on a SVR4, you automatically have a
bidirectional ring as far as you don't use the stdio routines
to access the pipe. That is, if you access the file descriptors
directly with write() and read(), it is perfectly valid for your
ring to write to fd 0 ("stdin") and read from fd 1 ("stdout").

If you want to use the stdio routines, you could add something
like this (not tested though)

[...]
      int   error;         /* return value from dup2 call                */
      int   status;
+      FILE *STDINREV, *STDOUTREV; /* FILE descriptors to write to the previous
+                                     or read from the next process in the ring */
[...]
      if (childpid)
             break;
       }
    }
+
+    /* now create new FILE descriptors for the reverse direction in the ring */
+    if ( (STDOUTREV = fdopen(STDIN_FILENO, "w")) == NULL ||
+         (STDINREV = fdopen(STDOUT_FILENO, "r")) == NULL ) {
+            perror("Could not open descriptor for reverse direction");
+            exit(1);
+    }
+
   wait(&status);
[...]

to your code and use e.g. fprintf(STDOUTREV,"whatever\n") to
write to the previous process.
This is not portable though, for example Linux doesn't know this
new semantic of pipe().

To implement it in a portable way, you just have to open up a
second pipe for the reverse direction, and in case you want to
use STDIO on this as well, use the fdopen() method to get FILE*
descriptors for these pipes as well. One thing is different though, you might run into problems if you want fixed fd's for
the reverse direction (say, fd 3 and 4). To be on the safe side,
you should access the new pipes via variables containing the fd.

Do you need code for this or do you want to try yourself?

0
 

Author Comment

by:pete_host
ID: 1292668
Hi mrausch,
thank you for your help on this problem. Actually, i still have a little bit confused about this problem. Can you show me the code for this problem? I am running linux for this problem.


0
 
LVL 2

Expert Comment

by:seedy
ID: 1292669
Home assignment?!  pete_host, why don't you post what you have coded so far?
0
What does it mean to be "Always On"?

Is your cloud always on? With an Always On cloud you won't have to worry about downtime for maintenance or software application code updates, ensuring that your bottom line isn't affected.

 

Author Comment

by:pete_host
ID: 1292670
here is the code i have, but i don't know why it is not working right?

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


void main(int argc, char *argv[])
{
      
      int  i;
      int childpid;
      int nprocs;
      int fd[2];
      int error;
      int p1[2];
      int p2[2];
      int p3[2];
      int p4[2];
      int start=1;


      if ((argc !=2)|| ((nprocs = atoi(argv[1]))<=0)) {
      fprintf (stderr, "Usage: %s processes\n", argv[0]);
      exit (1);

      }
      if (pipe (p1) == -1) {
          perror("Could not create pipe1");
          exit(1);
      }
      if (pipe (p2) == -1) {
          perror("Could not create pipe2");
          exit(1);
      }
      if (pipe (p3) == -1) {
          perror("Could not create pipe3");
          exit(1);
      }
      if (pipe (p4) == -1) {
          perror("Could not create pipe4");
          exit(1);
      }
      if ((childpid= fork()) == -1) {
            fprintf(stderr, "Could not create child %d: %s \n",
            i, strerror(errno));
            exit(1);
            }
      if (childpid){
            if ((dup2(p2[0], p1[1]) == -1) ||
                (dup2(p3[0], p2[0]) == -1)||
                (dup2(p4[1], p2[1]) == -1)){
                  perror("Could not dup pipes");
                  exit(1); }

            if ((close(p3[0]) == -1) || (close(p3[1]) == -1) ||
                      (close(p4[0]) == -1) || (close(p4[1]) == -1)){
                   perror("Could not close extra descriptors");
                  exit(1);}
                }
      else{
            if ((dup2(p1[1], p1[0]) == -1) ||
                (dup2(p2[0], p1[1]) == -1)||
                (dup2(p3[1], p2[0]) == -1)||
                (dup2(p4[0], p2[1]) == -1)){
                  perror("Could not dup pipes");
                  exit(1); }
            if ((close(p3[0]) == -1) || (close(p3[1]) == -1) ||
                      (close(p4[0]) == -1) || (close(p4[1]) == -1)){
                   perror("Could not close extra descriptors");
                  exit(1);}
          }

      for (i=1; i<nprocs; i++) {
            if (i==1) { break;};

      if (childpid){
            if ((dup2(p2[0], p1[0]) == -1) ||
                (dup2(p2[1], p1[1]) == -1)||
                (dup2(p3[0], p2[0]) == -1)||
                (dup2(p4[1], p2[1]) == -1)){
                  perror("Could not dup pipes");
                  exit(1); }
            if ((close(p3[0]) == -1) || (close(p3[1]) == -1) ||
                      (close(p4[0]) == -1) || (close(p4[1]) == -1)){
                   perror("Could not close extra descriptors");
                  exit(1);}
            break;}
      else {
            if ((dup2(p3[1], p2[0]) == -1) ||
                (dup2(p4[0], p2[1]) == -1)){
                  perror("Could not dup pipes");
                  exit(1); }
            if ((close(p3[0]) == -1) || (close(p3[1]) == -1) ||
                      (close(p4[0]) == -1) || (close(p4[1]) == -1)){
                   perror("Could not close extra descriptors");
                  exit(1);}
            
            if (pipe(p3) == -1) {
            fprintf(stderr, "Could not create child %d: %s \n",
            i, strerror(errno));
            exit(1);
            }
            if (pipe(p4) == -1) {
            fprintf(stderr, "Could not create child %d: %s \n",
            i, strerror(errno));
            exit(1);
            }
            if ((childpid= fork()) == -1) {
            fprintf(stderr, "Could not create child %d: %s \n",
            i, strerror(errno));
            exit(1);
            }
      }
   }
   fprintf(stderr, "process #i:%d process ID: %ld parent ID: %ld \n",
    i, (int) getpid(), (int) getppid());
      exit(0);
}

0
 

Author Comment

by:pete_host
ID: 1292671
Adjusted points to 250
0
 

Author Comment

by:pete_host
ID: 1292672
anybody help me on this? I need to hand in the hw tomorrow!
0
 
LVL 2

Expert Comment

by:seedy
ID: 1292673
Please see the question "Token Ring(Bidirectional)" under C Language topic area, at:
http://www.experts-exchange.com/topics/comp/lang/c/Q.10050266

0

Featured Post

On Demand Webinar: Networking for the Cloud Era

Did you know SD-WANs can improve network connectivity? Check out this webinar to learn how an SD-WAN simplified, one-click tool can help you migrate and manage data in the cloud.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Introduction: The undo support, implementing a stack. Continuing from the eigth article about sudoku.   We need a mechanism to keep track of the digits entered so as to implement an undo mechanism.  This should be a ‘Last In First Out’ collec…
Exception Handling is in the core of any application that is able to dignify its name. In this article, I'll guide you through the process of writing a DRY (Don't Repeat Yourself) Exception Handling mechanism, using Aspect Oriented Programming.
This video will show you how to get GIT to work in Eclipse.   It will walk you through how to install the EGit plugin in eclipse and how to checkout an existing repository.
In this video, Percona Director of Solution Engineering Jon Tobin discusses the function and features of Percona Server for MongoDB. How Percona can help Percona can help you determine if Percona Server for MongoDB is the right solution for …

688 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question