• 0

[c++] Semaphores


Question

Hey all. I have an assignment to use a semaphore class with. I'm a little confused by how they work though. [Our teacher speaka no english]

So anywho what we have are 3 Processes that are communicating (a parent and two child processes). Trying to simply the problem basically the two children pass random numbers and their Process Identification Number (PID) to the Parent process via a pipe. Both pieces of data are integers. Basically what we are to use the semaphores for is to have the parent process alternate between the two children as they write to the parent.

For example:

Both children wait for the parent to tell them to write to it (the parent), and the parent alternates between Child1 and Child2; so that the output stream is Child1's data, Child2's data, Child1's data, Child2's data...etc.

I just really need clarification on the what the semaphore does. I know it protects the critical data, but how I am to use it I'm fuzzy on.

I don't know if anyone could just write a line or two of code with a semaphore allowing access to a piece of critical data? I'm familiar with how to declare the semaphore and its member functions, implementation is my weak point.

If you have any good websites or applets that deal with them thats sweet too, I googled but to no avail. The program is being written on a UNIX server. Thanks in advance everyone! :pinch:

Link to comment
Share on other sites

5 answers to this question

Recommended Posts

  • 0

http://www.cs.cf.ac.uk/Dave/C/node26.html#...000000000000000

http://docs.linux.cz/programming/c/unix_examples/semab.html

http://www.ecst.csuchico.edu/~beej/guide/ipc/semaphores.html

http://www.catb.org/~esr/cookbook/

You may want to google ipc semaphores or UNIX semaphores for more. You are using System V semaphores and not Posix semaphores, right? If not, just search for POSIX pthreads semaphore... etc.

Link to comment
Share on other sites

  • 0
http://www.cs.cf.ac.uk/Dave/C/node26.html#...000000000000000

http://docs.linux.cz/programming/c/unix_examples/semab.html

http://www.ecst.csuchico.edu/~beej/guide/ipc/semaphores.html

http://www.catb.org/~esr/cookbook/

You may want to google ipc semaphores or UNIX semaphores for more. You are using System V semaphores and not Posix semaphores, right? If not, just search for POSIX pthreads semaphore... etc.

584830161[/snapback]

Well we aren't using STL semaphores, its a user (professor) defined class :wacko:

I'm just unclear on how they are to be implemented in keeping data protected.

Thanks for the links tho, but I don't think they're what I need, overcomplicated I'm afraid :cry:

Link to comment
Share on other sites

  • 0
Well we aren't using STL semaphores, its a user (professor) defined class  :wacko:

I'm just unclear on how they are to be implemented in keeping data protected.

Thanks for the links tho, but I don't think they're what I need, overcomplicated I'm afraid  :cry:

584830179[/snapback]

STL doesn't do IPC/Threading. That stuff it platform specific. If you would, post your professor's class. Maybe we can help.

Link to comment
Share on other sites

  • 0

basically resources have semaphores or groups of semaphores that allow other processes to access them without interfering with each other or corrupting data. here's a small example without knowing any details of your processes:

child1
{
     while(1)
     {
          parent.sem_P();
          parent.write();
          parent.sem_V();
     }
}

child2
{
     while(1)
     {
          parent.sem_P();
          parent.write();
          parent.sem_V();
     }
}

your parent process would then need to control access to the semaphore object so the child1 and child2 processes alternate independent of their priorities. hope that helps. and yeah post some of your code.

Link to comment
Share on other sites

  • 0

Thanks for the help so far guys!

Here's the semaphore.h file that our teacher has us include in our program.

/////////////////////////////////////////////////////////////////////////

// File:        semaphore.h

//////////////////////////////////////////////////////////////////////////

#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <errno.h>

union semun {
    int val;
    struct      semid_ds        *buf;
    ushort      *array;
};

class Semaphore {

  private:
    const unsigned int  SemCount;
    int                 SemID;

  public:

    // Create a semaphore group .  Return the semaphore id for the group.
    Semaphore (key_t key, int howManySemaphoresToCreate);

    //For example, use key 1234 to create 10 semaphores 0 through 9 ...
    //Semaphore semHandle (1234, 10);

    // Set the initial value of a semaphore.
    void Init (int SemaphoreNumber, int Value);


    // Return the current value of the semaphore, semaphoreNumber
    int ReadValue (int SemaphoreNumber);


    // Decrease the value of a semaphore, semaphoreNumber, by 1
    // BLOCKS if prev value is 0!!!
    void Wait (int SemaphoreNumber);

    // Increase the value of a semaphore, semaphoreNumber, by 1.
    void Signal (int SemaphoreNumber);

    // Remove all semaphores.
    void Destroy( );
};

This is the program that we are supposed to put the semaphores in. We are to replace the two sync pipes with semaphores. So that the children don't wait to read from the parent, they use semaphores for that.

/**************************************************************
*  CS 327 - Fall, 2004                     Lab Assignment #1  *
*                                                             *
*  Problem:                                                   *
*     This assignment deals with the communication between    *
*     three processes.  The "Parent" creates two children.    *
*     Each child generates n random numbers and send each     *
*     number with its ID to the parent through a single pipe. *
*     Each child process uses getpid() system call to find    *
*     its ID and generates a random number and sends both of  *
*     these numbers to the parent process.                    *
*                                                             *
*     Using process synchronization the two child processes   *
*     send their information (ID and random number) in an     *
*     alternate way.  This is done by using two additional    *
*     pipes and the parent decides who goes next.  Each child *
*     first reads from parent (gets a permission) and then    *
*     sends its information to parent.  Each child then uses  *
*     the usleep() system call to block itself temporarily.   *
*                                                             *
*     The seed for random numbers and the count for random    *
*     numbers are the command line arguments.  Therefore, to  *
*     run the program we use:                                 *
*            a.out  seed1  seed2  numRandom                   *
*                                                             *
**************************************************************/
#include <sys/types.h>
#include <iostream.h>
#include <unistd.h>
#include <stdlib.h>
#include <signal.h>

int main(int argc, char *argv[])
 {
   // check for the number of arguments
   if (argc != 4)
     { cout << "You must supply two seeds and the number of "
            << "random numbers." << endl;
       exit(1);
     }

   int pid1, pid2, i, count;
   int mainPipe[2], pipe1[2], pipe2[2], buffer[2], SynchBuff[1];
   count = atoi (argv[3]);
   if (count <= 0) // exit if no number to be generated
     { cout << "Parent: No number was generated." << endl;
       exit(1);
     }

   // create the main pipe, and exit if it fails
   if (pipe(mainPipe) < 0 )
      {
        cout << "The main pipe cannot be created" << endl;
        exit(1);
      }
   // create the synchronization pipe for child1, and exit if it fails
   if ( (pipe(pipe1) < 0 ) )
      {
        cout << "The synchronization pipe cannot be created" << endl;
        exit(1);
      }

   // create the first child
   pid1 = fork();
   if (pid1 == -1)
      {
         cerr << "The child process could not be created." << endl;
         exit(1);
      }
   //**************************************************** Child1 ***
   if (pid1 == 0)
     {
        int seed1 = atoi (argv[1]);
        srand(seed1);
        close (mainPipe[0]);  // does not read from the main pipe
        close (pipe1[1]);     // does not write to the synch pipe1

        pid1 = getpid();  
        // wait for your turn and then generate random numbers 
        // and send them to the parent along with your ID
        for (i=0; i<count; i++)
           {
              read(pipe1[0], buffer, 4);

              buffer[0] = pid1;
              buffer[1] = rand() % 1000;
              write(mainPipe[1], buffer, 8);
              usleep(1000);
           }
        close(pipe1[0]);
        close (mainPipe[1]);
        exit(0);
     }                // end of child1 process
     //**************************************************************

   // parent process continues
   else
     {
          // create the synch. pipe for child2, and exit if it fails
          if ( (pipe(pipe2) < 0 ) )
            {
             cout <<"The synchronization pipe cannot be created" << endl;
             kill (pid1, SIGKILL);  // terminate child1
             exit(1);
            }

         // create the second child
         pid2 = fork();
         if (pid2 == -1)
            {
               cerr << "The child process could not be created." << endl;
               kill (pid1, SIGKILL);  // terminate child1
               exit(1);
            }

         //*********************************************** Child2 ***
         if (pid2 == 0)
           {
              int seed2 = atoi (argv[2]);
              srand(seed2);

              close (mainPipe[0]);  // does not read from the main pipe
              close (pipe2[1]);     // does not write to the synch pipe2
              close (pipe1[0]);     // does not deal with first synch pipe
              close (pipe1[1]);

              pid2 = getpid();  
              // wait for your turn and then generate random numbers 
              // and sent them to the parent along with your ID
              for (i=0; i<count; i++)
                 {
                    read(pipe2[0], buffer, 4);

                    buffer[0] = pid2;
                    buffer[1] = rand() % 1000;
                    write(mainPipe[1], buffer, 8);
                    usleep(1000);
                 }
              close(pipe2[0]);
              close (mainPipe[1]);

              exit(0);
      
           }     // end of child2 process
           //********************************************************

          else
            {
              // parent process continues
              // close unused ends of pipes
              close(mainPipe[1]);
              close(pipe1[0]);
              close(pipe2[0]);

              SynchBuff[0] = 1;

              // Send the synchronization message to the children
              // processes and read the information sent by children.
              // Also keep track of the smallest number received

              int minimum;
              minimum = 1000;

              for (i=0; i<count; i++)
                 {
                    // Write to child 1 and read from child 1
                    write(pipe1[1], SynchBuff, 4);
                    read(mainPipe[0], buffer, 8);
                    if (buffer[1] < minimum)
                       minimum = buffer[1];

                    cout << " The child ID is: " << buffer[0]
                         << " and the number received is: " << buffer[1]
                         << endl;

                    // Write to child 2 and read from child 2

                    write(pipe2[1], SynchBuff, 4);
                    read(mainPipe[0], buffer, 8);
                    if (buffer[1] < minimum)
                       minimum = buffer[1];

                    cout << " The child ID is: " << buffer[0]
                         << " and the number received is: " << buffer[1]
                         << endl;

                  }

               cout << endl;
               cout << " Parent: The minimum of all numbers received is: "
                    << minimum << endl;

               // close the pipes
               close(mainPipe[0]);
               close(pipe1[1]);
               close(pipe2[1]);
               exit (0);

            }  /* end of parent process */
     }
 }

OUTPUT HERE

/*****************************************************************
$
$ g++ lab1key.cpp
$
$ a.out  21329  139001  0
Parent: No number was generated.
$
$
$ a.out  2703  1501  2
 The child ID is: 2540 and the number received is: 958
 The child ID is: 2541 and the number received is: 170
 The child ID is: 2540 and the number received is: 296
 The child ID is: 2541 and the number received is: 855

 Parent: The minimum of all numbers received is: 170
$
$
$ a.out  3089  4907  5
 The child ID is: 2580 and the number received is: 712
 The child ID is: 2581 and the number received is: 441
 The child ID is: 2580 and the number received is: 549
 The child ID is: 2581 and the number received is: 793
 The child ID is: 2580 and the number received is: 174
 The child ID is: 2581 and the number received is: 388
 The child ID is: 2580 and the number received is: 384
 The child ID is: 2581 and the number received is: 690
 The child ID is: 2580 and the number received is: 91
 The child ID is: 2581 and the number received is: 686

 Parent: The minimum of all numbers received is: 91
$
************************************************************/

A lot of code I know :(

Thanks for all your help guys! (Maybe you're getting some practice out of this lol) :rofl:

Link to comment
Share on other sites

This topic is now closed to further replies.
  • Recently Browsing   0 members

    • No registered users viewing this page.