For Programmers: Free Programming Magazines  


Home > Archive > Unix Programming > May 2004 > fork & exec: sharing memory between a parent and a child.









You are viewing an archived Text-only version of the thread. To view this thread in it's original format and/or if you want to reply to this thread please [click here]

 

Author fork & exec: sharing memory between a parent and a child.
Zack

2004-05-18, 3:42 pm

Hi,

Please can someone help me with the following problem:

I have a server that listens for events and should spawn a child
process
using fork & exec approach for every caught event so that child could
handle farther event processing. All child logic is in program that
is called with exec.

The problem I have is that when the parent process starts, it creates
the shared memory block (with shmget function) that needs to be shared
among all childer. Childred then will use shmat to map the memory,
etc. However, it seems that the exec method prevents children from
sharing this memory block with the parent and other children.

How can I pass the current state of the shared memory from
parent to child and from child to parent. A small example would be
very good because I am a complete novice in this kind of programs.

P.S. I am on Solaris 9, using SunWorkshop.
Barry Margolin

2004-05-18, 6:31 pm

In article <a5f6b9a8.0405181058.36b50982@posting.google.com>,
uzmargov@yahoo.com (Zack) wrote:

> Hi,
>
> Please can someone help me with the following problem:
>
> I have a server that listens for events and should spawn a child
> process
> using fork & exec approach for every caught event so that child could
> handle farther event processing. All child logic is in program that
> is called with exec.
>
> The problem I have is that when the parent process starts, it creates
> the shared memory block (with shmget function) that needs to be shared
> among all childer. Childred then will use shmat to map the memory,
> etc. However, it seems that the exec method prevents children from
> sharing this memory block with the parent and other children.


The child must use shmat *after* it execs the new program, since exec
completely resets the state of the process's memory. Pass the ID of the
shared memory to the program as a command-line argument in argv[].

--
Barry Margolin, barmar@alum.mit.edu
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***
Zack

2004-05-21, 6:32 pm

I am re-writing a program that uses fork to create child processes to
use fork and exec approach. The parent process creates a shared memory
region.
The shared memory must be shared and updated by the child program that
is specified in exec. There can be ran more then one child program
simultaneously.
The Parent program uses shmget function to create the shared memory
region.
Then each child program updates the shared area using shmat function.

The problem I am having is that before I map the memory in the child
program (shmat) I need to lock the shared memory region to make sure
that other children do not update the same region at the same time.

However, even though program works with fork method, it does not work
with fork & exec. A Child program simply hangs in semop function.
Can any one explain what can cause semop to hang in this case?
Barry Margolin

2004-05-21, 8:31 pm

In article <a5f6b9a8.0405211307.6216ba94@posting.google.com>,
uzmargov@yahoo.com (Zack) wrote:

> The problem I am having is that before I map the memory in the child
> program (shmat) I need to lock the shared memory region to make sure
> that other children do not update the same region at the same time.
>
> However, even though program works with fork method, it does not work
> with fork & exec. A Child program simply hangs in semop function.
> Can any one explain what can cause semop to hang in this case?


You have access to the source code and you can't troubleshoot it. You
expect us to do better without seeing a single bit of code?

How does the exec'ed program find out what semaphore to use?

BTW, since your problem is with semaphores, why do you emphasize shared
memory in the Subject line? It's likely that the shared memory is
totally irrelevant.

--
Barry Margolin, barmar@alum.mit.edu
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***
David Logan

2004-05-22, 1:32 am

Barry Margolin wrote:
> In article <a5f6b9a8.0405211307.6216ba94@posting.google.com>,
> uzmargov@yahoo.com (Zack) wrote:
>
>
>
>
> You have access to the source code and you can't troubleshoot it. You
> expect us to do better without seeing a single bit of code?
>
> How does the exec'ed program find out what semaphore to use?
>
> BTW, since your problem is with semaphores, why do you emphasize shared
> memory in the Subject line? It's likely that the shared memory is
> totally irrelevant.
>

Also, fork() does not use the same memory. Although the following
statement is not technically 100% true, it is logically true:

fork() creates a copy of the original address space and begins running a
new process in it. Any changes made to one address space will not be
reflected in the other.

In order for two threads to use the same address space, you need to use
pthreads or something similar.

....

The technical truth is that after a fork(), both the parent and the
child point to the same pages. No actual duplication takes place until a
write occurs. Once one of the processes writes to a segment of memory,
THEN that memory is copied local to the address space. But in effect,
both processes still have their own unique copies.

fork()'d processes need to use shared memory (your semaphore probably
isn't in shared memory), pipes or some other communication method.

David Logan
Barry Margolin

2004-05-22, 6:31 pm

In article <tqArc.93956$xw3.5366791@attbi_s04>,
David Logan <djlogan2@comcast.net> wrote:

> fork()'d processes need to use shared memory (your semaphore probably
> isn't in shared memory), pipes or some other communication method.


That's what the OP is doing. Semaphores are a communication method.

--
Barry Margolin, barmar@alum.mit.edu
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***
David Logan

2004-05-22, 10:31 pm

Barry Margolin wrote:
> In article <tqArc.93956$xw3.5366791@attbi_s04>,
> David Logan <djlogan2@comcast.net> wrote:
>
>
>
>
> That's what the OP is doing. Semaphores are a communication method.
>

I do not believe semaphores are in shared memory by default. I believe
they are private to a process by default. But, without looking it up, I
could be wrong.

David Logan
Barry Margolin

2004-05-23, 2:31 am

In article <40AFFEE2.2000406@comcast.net>,
David Logan <djlogan2@comcast.net> wrote:

> Barry Margolin wrote:
> I do not believe semaphores are in shared memory by default. I believe
> they are private to a process by default. But, without looking it up, I
> could be wrong.


Argghh! Why did you send that as email to me? I didn't know you also
posted it to the group (see my sig).

Like I said in my private response, semaphores aren't in user memory at
all -- they're referenced using an IPC ID, analogous to the way file
descriptors are used to refer to an open file, except that IPC IDs are
system-wide. Semaphores are used for mutual exclusion between processes.

--
Barry Margolin, barmar@alum.mit.edu
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***
Zack

2004-05-24, 12:35 pm

Sorry for the confusion, as I said I am a complete novice in this
kinds of programs. Following is the code snapshot (It will not
compile, but you would have an idea).

/ ****************************************
****/
/ ****************************************
****/
/******** PARENT CODE ***********************/
/ ****************************************
****/
#include "sharedMem.h"
class wmsSharedMem;
extern SharedMem sharedMem;

// Global vars
BOOLEAN sharedMemCreated; // Boolean is a UDT
/ ****************************************
****/
// methods sigs.
int Agent_initialize(); // does various server inits
int sharedMemCleanup(); // Cleans the shared memory from previous
run
void EventAgentStart(); // Start listening for events.
void onMsg (char* message); // consumes the events
/ ****************************************
****/
int main(int argc, char** argv)
{
Agent_initialize ();
EventAgentStart();
return 0;
}

/ ****************************************
*****/
int Agent_initialize ()
{
// Do various stuff that is unrelated
// to the issue posted
//.............
//............
signal(SIGHUP, (SIG_PF)sharedMemCleanup);
signal(SIGINT, (SIG_PF)sharedMemCleanup);
signal(SIGKILL, (SIG_PF)sharedMemCleanup);
signal(SIGTERM, (SIG_PF)sharedMemCleanup);
signal(SIGSTOP, (SIG_PF)sharedMemCleanup);
signal(SIGCLD, (SIG_PF)SIG_IGN);

sharedMemCreated = FALSE;
//...............
//...............
}
/ ****************************************
*****/
void EventAgentStart()
{
// Starts event listener
// The events then are caught by onMsg function
// ...................
//.................
}
/ ****************************************
*****/
void onMsg (char* message)
{
pid_t pId;

if (sharedMemCreated == FALSE)
{
if (sharedMem.wmsCreate(0, 4096,0666)==-1)
// Handle errors
else
sharedMemCreated = TRUE;
}
if ((pId = fork()) == 0)
{
// See code for Agents_Child
if ( execl("Agents_Child","Agents_Child", NULL) < 0 )
{
// handle errors
}
exit(0);
}
else if (pId == -1)
{
// Handle error
}
}
/ ****************************************
*****/
int sharedMemCleanup()
{
int ret_var;
int i;
char buf[250], *p;
FILE *in;

if ((ret_var = sharedMem.wmsDestroy()) < 0)
cout << "error: " << sharedMem.getLastError() << endl;

cout.flush();
return(0);
}
/ ****************************************
*****/
/ ****************************************
****/
/ ****************************************
****/
/******** CHILD'S CODE **********************/
/ ****************************************
****/
#include "sharedMem.h"
class wmsSharedMem;
extern SharedMem sharedMem;
/ ****************************************
****/
void child_func()
{
char *p;

if ((p = sharedMem.wmsMap(WMS_SHMEM_QUEUE_REGION)) != (char *) -1)
{
// Do stuff ...
}
sharedMem.wmsUnMap(WMS_SHMEM_QUEUE_REGION);
}
/ ****************************************
****/
int main()
{

child_func();
return (0);
}
/ ****************************************
*****/
/ ****************************************
*****/
/************* SHARED MEMORY MODULE **********/
/ ****************************************
*****/
extern "C"
{
#include <stdlib.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/sem.h>
}
//---------------------
// Semaphore defines
//---------------------
#define SEM_PERM 0666 // give permission to everyone
#define SHARED_REGIONS 2 // number of shared memory regions
to create


//---------------------
// Region defines
//---------------------
#define WMS_SHMEM_QUEUE_REGION 0
#define WMS_SHMEM_COMPUTER_REGION 1


//--------------------------------------------
// Declarations
//--------------------------------------------
typedef struct
{
struct sembuf opLock[2],
opUnLock[1];
} WMS_SEM_DEF;

typedef struct
{
int shmKey;
int semKey;
int shmSize;
int shmId;
int semId;
char *shmPntr;
} WMS_SHARED_DEF;

//----------------------------------------------
// Class Declaration
//----------------------------------------------
class SharedMem
{
private:
WMS_SHARED_DEF wmsVar[SHARED_REGIONS];
WMS_SEM_DEF wmsSem[SHARED_REGIONS];
int m_NumRegions;
char m_errorString[256];

private:
int wmsLock (char regNum);
int wmsUnLock (char regNum);
void wmsDestroyLock (char regNum);

public:
wmsSharedMem (void);
~wmsSharedMem (void) {}
int wmsCreate (char regNum, int size, int flag);
int wmsDestroy (void);
char* wmsMap (char regNum);
int wmsUnMap (char regNum);
char* getLastError (void) { return(m_errorString); }
};

SharedMem sharedMem;

//-----------------------------------------------
// Shared memory and semaphore structures
//-----------------------------------------------
static struct sembuf opLock[2] = {0, 0, 0, 0, 1, SEM_UNDO};
static struct sembuf opUnLock[1] = {0, -1, (IPC_NOWAIT | SEM_UNDO)};


SharedMem::SharedMem(void)
{
int i;

m_NumRegions = 0;

for (i=0; i<SHARED_REGIONS; i++)
{
wmsVar[i].shmPntr = NULL;
wmsVar[i].semId = -1;
wmsVar[i].shmKey = 7891 + i;
wmsVar[i].semKey = 223456 + i;

memcpy(&wmsSem[i].opLock[0], &opLock[0], sizeof(struct
sembuf) * 2);
memcpy(&wmsSem[i].opUnLock[0], &opUnLock[0], sizeof(struct
sembuf));
}
}

int SharedMem::wmsCreate(char regNum, int size, int perm=0666)
{
wmsVar[regNum].shmSize = size;

if ((wmsVar[regNum].shmId = shmget(wmsVar[regNum].shmKey,
wmsVar[regNum].shmSize, IPC_CREAT | perm))==-1)

{ // Handle Errors .... }

if (m_NumRegions <= regNum)
++m_NumRegions;

return(wmsVar[regNum].shmId);
}

int SharedMem::wmsDestroy(void)
{
int i, t;

for (t=0; t<m_NumRegions; t++)
{
wmsDestroyLock(t);

if ((i=shmctl(wmsVar[t].shmId, IPC_RMID,(struct shmid_ds *) 0))
< 0)
{
// Handle Errors .....
break;
}
}

return(i);
}

char* SharedMem::wmsMap(char regNum)
{
if (wmsLock(regNum)==0)
{
return((char *)-1);
}

if ((wmsVar[regNum].shmPntr =
(char *) shmat(wmsVar[regNum].shmId, (char *) 0, 0)) == (char *)
-1)
{
// Handle errors .......
}
return(wmsVar[regNum].shmPntr);
}

int SharedMem::wmsUnMap(char regNum)
{
int i;

if (wmsUnLock(regNum)==0)
return(-1);

if ((i=shmdt(wmsVar[regNum].shmPntr)) < 0)
// Handle Errors
else
wmsVar[regNum].shmPntr = NULL;

return(i);
}

int wmsSharedMem::wmsLock(char regNum)
{
if ((wmsVar[regNum].semId < 0) && ((wmsVar[regNum].semId =
semget(wmsVar[regNum].shmKey, 1, IPC_CREAT | SEM_PERM)) < 0))
{
// Handle Errors ......
return(0);
}

if (semop(wmsVar[regNum].semId, &wmsSem[regNum].opLock[0], 2) < 0)
{
// Handle errors ......
return(0);
}

return(1);
}

int SharedMem::wmsUnLock(char regNum)
{
if (semop(wmsVar[regNum].semId, &wmsSem[regNum].opUnLock[0], 1) < 0)
{
// Handle Errors
return(0);
}
return(1);
}

void SharedMem::wmsDestroyLock(char regNum)
{
if (semctl(wmsVar[regNum].semId, 0, IPC_RMID, 0) < 0)
// Handle Errors
}
Barry Margolin

2004-05-24, 6:35 pm

In article <a5f6b9a8.0405240709.197443f2@posting.google.com>,
uzmargov@yahoo.com (Zack) wrote:
> /******** CHILD'S CODE **********************/
> / ****************************************
****/
> #include "sharedMem.h"
> class wmsSharedMem;
> extern SharedMem sharedMem;
> / ****************************************
****/
> void child_func()
> {
> char *p;
>
> if ((p = sharedMem.wmsMap(WMS_SHMEM_QUEUE_REGION)) != (char *) -1)
> {
> // Do stuff ...
> }
> sharedMem.wmsUnMap(WMS_SHMEM_QUEUE_REGION);
> }


The child never calls any member function that updates sharedMem.shmId
before calling shmat(). So it's trying to attach to a shared memory
with ID -1, rather than the shared memory that was created by the parent.

--
Barry Margolin, barmar@alum.mit.edu
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***
Sponsored Links







Also available: Server administration forum archive | Web Design forum archive | Software forum archive | Hardware reviews archive

Copyright 2010 codecomments.com