Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Chris Miller on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Multiple processes sharing data in C++

Status
Not open for further replies.

Jen53403

Programmer
Jul 17, 2006
22
I'm trying to create a simple C++ program that uses fork() to create three processes which work together to calculate the square roots of all integers from 1 - 100. Each thread is supposed to read a common int, print out its root, and increment the int. My problem is I don't know how to get all three processes to share this integer! I tried a pointer, but that didn't help. What can I do?

Below is the code:
Code:
#include <sys/types.h>  // defines pid_t
#include <unistd.h>             // defines fork
#include <iostream>             // defines cout, cin
#include <stdlib.h>     // defines exit()
#include <math.h>               // defines sqrt()

using namespace std;

class Process
{
public:
   Process() {}
   int calcRoots(int* valuePtr);
private:
};

int Process::calcRoots(int* valuePtr)
{
      // Get process ID
      pid_t id = getpid();

      // Calculate
      while(*valuePtr <= 100)
           {
         cout << "P" << id << ":V" << *valuePtr << "=" << sqrt((double)(*valuePtr)) << "  ";
              if (*valuePtr % 4 == 0)
                        cout << endl;
                        *valuePtr += 1;
      }  // while

      exit(0);   // do not return
}  // calcRoots()

int main()
{
      Process child;
          int value = 1;

      // Create three children to calculate the roots.
      if (fork() == 0)  // child process
         child.calcRoots(&value);
      if (fork() == 0)  // child process
         child.calcRoots(&value);
      if (fork() == 0)  // child process
         child.calcRoots(&value);
}  // main()
 
Since it looks like you're writing a UNIX program, the "C++ UNIX" forum would have been a better place to post.

I believe the functions you need to use are the sh* family of functions such as:
shmid(), shmat(), shmctl(), shmget(), shmdt()...

I've never used them myself, but you can probably figure out what you need to do if you look at the MAN pages for those functions.
 
On Windows, you use CreateProcess instead of fork.

Sharing data is the same as Unix. You can use memory mapping but the behavior is different. On Unix, one process creates the mapped memory and the others just use it. For simplicity, the process that opens the mapped memory should close it.

On Windows, each process can hold the handle to the mapped memory but unless they map it, they cannot see it. Unlike Unix, only one process can map the memory. The others will be blocked until the process that holds the map releases it.

If you don't wish to play with memory mapping, just use a simple file. One writes to it and the others read from it. After all, that is what memory mapping is except that the file is in memory instead of being on a disk.
 
Well I've implemented the shared memory, and it seems to be working fine, but now I've discovered another defect - each process is running through and completing its execution before the next process is created! They should all be running simultaneously; that was the point of my experiment. Here's the newer version of my code:

Code:
#include <sys/types.h>  // defines pid_t
#include <unistd.h>             // defines fork
#include <iostream>             // defines cout, cin
#include <stdlib.h>     // defines exit()
#include <math.h>               // defines sqrt()
#include <sys/shm.h>

using namespace std;

class Process
{
public:
   Process() {}
   int calcRoots(int shmid);
private:
};

int Process::calcRoots(int shmid)
{
      // Get process ID
      pid_t id = getpid();

      // Attach self to shared memory segment
      void* shm;
      shm = shmat(shmid, NULL, 0);
      int* a = (int*)shm;

      // Calculate
      while(*a <= 100)
           {
         cout << "P" << id << ":V" << *a << "=" << sqrt((double)(*a)) << "  ";
         if (*a % 4 == 0)
              cout << endl;
         *a += 1;
      }  // while

      shmdt(shm);  // Detach from shared memory segment

      exit(0);   // do not return
}  // calcRoots()

int main()
{
      Process child;
      int value = 1;

      key_t key;
      int shmid;

      key = 12345;
      shmid = shmget(key, 1024, 0644 | IPC_CREAT);

      // Create three children to calculate the roots.
      if (fork() == 0)  // child process
         child.calcRoots(shmid);
      if (fork() == 0)  // child process
         child.calcRoots(shmid);
      if (fork() == 0)  // child process
         child.calcRoots(shmid);

		// wait for children to finish executing
		wait();
		wait();
		wait();
      shmctl(shmid, IPC_RMID, NULL);
}  // main()
 
It is possible that the task is so short, it doesn't take very long to finish it. You could either make a longer task with more iterations or put in extra waits in the tasks.

Another alternative is for all of them to wait for a semaphore . You don't have to implement it as a semaphore in shared memory. Instead of having just one integer, you could have 2. One for the semaphore and one for the actual data. On initialization, all tasks will poll the semaphore and sleep. When all the tasks have been created, the master will change the value of the semaphore and all the tasks can get going.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top