Shared Memory...Some Questions..... - Linux
This is a discussion on Shared Memory...Some Questions..... - Linux ; All,
I having trouble getting a simple example of a shared memory example
to work;
I have never worked with shared memory and any suggestions/code hints/
examples would be greatly appreciated.
>From my reading you have to use shmget to ...
-
Shared Memory...Some Questions.....
All,
I having trouble getting a simple example of a shared memory example
to work;
I have never worked with shared memory and any suggestions/code hints/
examples would be greatly appreciated.
>From my reading you have to use shmget to specify that you need a
specific size of memory to be shared and then you use shmat to attach
it to a specific process.
My thinking, which is flawed, is that the child adding the 1099 to
what I believe the shared integer variable would then be "shared" to
the parent's final output of the procee id and the shared variable
( cout<<"Parent "<
when ran for the parents final output is not 1099 but is the value
99.
int main (void)
{
int indexId = 0;
if((indexId = shmget(IPC_PRIVATE,sizeof(int),SHM_R|SHM_W))<0)
{
cout<<"ERROR: indexId ="<
cout<
exit (1);
}
int ptheSharedIndex;
ptheSharedIndex = (int)shmat(indexId,0,0); //attach to the current
process
ptheSharedIndex = 99;
int k = 0;
while (k
{
pid = 0;
k=k+1;
pid = fork();
if (pid == 0)
{break;}
}
if (pid == 0) /* child process */
{
int indexIdChild = 0;
if((indexIdChild = shmget(key,sizeof(int),SHM_R|SHM_W))<0)
{
cout<<" CHILD ERROR: indexIdChild "<
}
int ctheSharedIndex;
ctheSharedIndex = (int)shmat(indexIdChild,0,0);
*/
/* int ctheSharedIndex;
ctheSharedIndex = (int)shmat(indexId,0,0);*/
cout<
ptheSharedIndex = 1099;
}
else /* parent */
{
sleep(8);
cout<<"Parent "<
}
exit(0); //End Process (Main)
}
Thanks for the help,
Chris
-
Re: Shared Memory...Some Questions.....
Solomon_Man wrote:
> int indexId = 0;
> if((indexId = shmget(IPC_PRIVATE,sizeof(int),SHM_R|SHM_W))<0)
> {
> cout<<"ERROR: indexId ="<
> cout<
> exit (1);
> }
You have an error in you method of programming here, in particular for C++
you could do better. Suggestion:
int shm_create( size_t size, int flags)
{
int res = shmget( IPC_PRIVATE, size, flags);
if(res!=-1)
return res;
int const e = errno;
cout << "shmget() failed, errno=" << e << '(' << strerror(e) << ")\n";
exit(EXIT_FAILURE);
}
What's the difference?
1. You are doing things between shmget() and reading errno that might
affect errno. Save the value immediately!
2. Use EXIT_FAILURE, it documents clearly what is going on.
3. No need to init a variable to zero and then assign a value to it. In
fact I'd consider the if-clause pretty unreadable. Suggestion:
int indexId = shmget(...);
if(indexId == -1)
{ ... }
What else:
The function returns an int, but that is in fact a resource handle that can
be used to access the shared memory. You need to make sure that this
resource is correctly released after use. For that, use RAII (STW if that
doesn't mean anything to you yet). I would suggest you create a wrapper
that behaves like std::auto_ptr, all with its peculiar copying semantics.
With that in place, you could also use exceptions to signal errors which
makes the final code much, much clearer.
> int ptheSharedIndex;
> ptheSharedIndex = (int)shmat(indexId,0,0);
> //attach to the current process
Now, this is plainly wrong: You are casting a pointer to an integer. Do you
know the difference between a pointer-to-X and an X? Further, the rule is
to never use C style casts in C++. If you don't (yet) understand why, at
least accept this for now and don't stray from this path. FYI, the correct
cast is a static_cast and if you try to cast to the wrong type the
compiler will tell you about it as good as it can - the 'int' would have
been flagged as error.
> exit(0); //End Process (Main)
Unnecessary, you could have returned here or simply fallen off the end with
the same effect.
Uli
-
Re: Shared Memory...Some Questions.....
"Solomon_Man" wrote in
news:1174442771.089368.296510@b75g2000hsg.googlegr oups.com:
I'm by no means a shared memory expert...
> if (pid == 0) /* child process */
> {
> int indexIdChild = 0;
> if((indexIdChild =
> shmget(key,sizeof(int),SHM_R|SHM_W))<0)
> {
> cout<<" CHILD ERROR: indexIdChild "<
> }
A few things here...
Where does "key" come from? I did not see it declared prior to this
point. Same with
Attached memory segments are inherited across a fork, so you
shouldn't have to repeat the shmget/shmat in the children.
You specified IPC_PRIVATE as the key when you first called shmget
before the fork. If you want to be able to shmget the same segment
in another process, you neet to use the same key in all shmgets and
that key cannot be IPC_PRIVATE.
> int ctheSharedIndex;
> ctheSharedIndex = (int)shmat(indexIdChild,0,0);
> */
> /* int ctheSharedIndex;
> ctheSharedIndex = (int)shmat(indexId,0,0);*/
> cout<
> ptheSharedIndex = 1099;
As already pointed out, this is incorrect. shmat returns a pointer
to the shared segment. If you are not comfortable with pointers, I
suggest that you do some experimentation in a simple program
without shared memory first. Any decent C tutorial should explain
pointers.
shmat returns a "generic" pointer (void*) because it has no way of
knowing what you plan to use the segment for. In your case, since
you are using it to store an int, you need to store the return
value of shmat into an "int*", i.e., a pointer to an integer, so:
int* pTheSharedIndex = shmat( ... )
Then, to store a value there you would dereference the pointer:
*pTheSharedIndex = 1099;
which means "store 1099 in the integer that pTheSharedIndex point
to".
MV
--
I do not want replies; please follow-up to the group.
-
Re: Shared Memory...Some Questions.....
On Mar 21, 7:53 am, Martin Vuille wrote:
> "Solomon_Man" wrote innews:1174442771.089368.296510@b75g2000hsg.google groups.com:
>
> I'm by no means a shared memory expert...
>
> > if (pid == 0) /* child process */
> > {
> > int indexIdChild = 0;
> > if((indexIdChild =
> > shmget(key,sizeof(int),SHM_R|SHM_W))<0)
> > {
> > cout<<" CHILD ERROR: indexIdChild "<
> > }
>
> A few things here...
>
> Where does "key" come from? I did not see it declared prior to this
> point. Same with
>
> Attached memory segments are inherited across a fork, so you
> shouldn't have to repeat the shmget/shmat in the children.
>
> You specified IPC_PRIVATE as the key when you first called shmget
> before the fork. If you want to be able to shmget the same segment
> in another process, you neet to use the same key in all shmgets and
> that key cannot be IPC_PRIVATE.
>
> > int ctheSharedIndex;
> > ctheSharedIndex = (int)shmat(indexIdChild,0,0);
> > */
> > /* int ctheSharedIndex;
> > ctheSharedIndex = (int)shmat(indexId,0,0);*/
> > cout<
> > ptheSharedIndex = 1099;
>
> As already pointed out, this is incorrect. shmat returns a pointer
> to the shared segment. If you are not comfortable with pointers, I
> suggest that you do some experimentation in a simple program
> without shared memory first. Any decent C tutorial should explain
> pointers.
>
> shmat returns a "generic" pointer (void*) because it has no way of
> knowing what you plan to use the segment for. In your case, since
> you are using it to store an int, you need to store the return
> value of shmat into an "int*", i.e., a pointer to an integer, so:
>
> int* pTheSharedIndex = shmat( ... )
>
> Then, to store a value there you would dereference the pointer:
>
> *pTheSharedIndex = 1099;
>
> which means "store 1099 in the integer that pTheSharedIndex point
> to".
>
> MV
>
> --
> I do not want replies; please follow-up to the group.
All thanks so much for the help. I definetly was flawed on my way of
thinking for this example. 
I will recode the small test app and try and get it to work from all
your suggestions.
After posting this originally, I found a few examples checking the
return value of shmat ( == (void *)-1) and figured that I definetlly
had some issue with my original idea. Then I also read on a man page
at home where the child processes inherits the shared memory after a
fork. The key issue was a idea I tried after seeing a few examples
online, I gave up on that and went to IPC_PRIVATE instead of the key.
Again thank for the help and I will repost with what I come up with
later tonight.
Thanks,
Chris