Want to protect your cyber security and still get fast solutions? Ask a secure question today.Go Premium

x
?
Solved

help on a ring problem.

Posted on 1998-05-02
7
Medium Priority
?
394 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
  • 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
Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 

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

[Webinar On Demand] Database Backup and Recovery

Does your company store data on premises, off site, in the cloud, or a combination of these? If you answered “yes”, you need a data backup recovery plan that fits each and every platform. Watch now as as Percona teaches us how to build agile data backup recovery plan.

Question has a verified solution.

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

This is to be the first in a series of articles demonstrating the development of a complete windows based application using the MFC classes.  I’ll try to keep each article focused on one (or a couple) of the tasks that one may meet.   Introductio…
Introduction: Displaying information on the statusbar.   Continuing from the third article about sudoku.   Open the project in visual studio. Status bar – let’s display the timestamp there.  We need to get the timestamp from the document s…
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.
Enter Foreign and Special Characters Enter characters you can't find on a keyboard using its ASCII code ... and learn how to make a handy reference for yourself using Excel ~ Use these codes in any Windows application! ... whether it is a Micr…
Suggested Courses
Course of the Month15 days, 19 hours left to enroll

581 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