Hi all
I have a problem with the shmat() function. It works correctly when
one doesn't specify an address where the segment should be attached,
but fails when one does. To specify an address it must be alligned
and I did by using __attribute__ (aligned()). Still the function
fails. What is the most effective way for a solution
to this problem.
Thanks
Dirk
_________________________________________________________________
Add photos to your e-mail with MSN 8. Get 2 months FREE*.
http://join.msn.com/?page=features/featuredemail
"Dirk Bull" <[email protected]> writes:
> I have a problem with the shmat() function. It works correctly when
> one doesn't specify an address where the segment should be attached,
> but fails when one does. To specify an address it must be alligned
> and I did by using __attribute__ (aligned()). Still the function
> fails. What is the most effective way for a solution
> to this problem.
__attribute__(aligned()) has nothing to do with it--the address needs
to be page-aligned (ie on a multiple of 4K for ix86), unless SHM_RND
is set in the call. You also need to make sure nothing else is mapped
at the address you're trying to use...
-Doug
Doug, thanks for the reply. I've set SHM_RND in the call and used
"__attribute__ ((aligned(4096)))" during the the declaration of variable
global01_
(as shown below) such that it is aligned on a page boundary. I'm porting
code that was
written for a Unix system to Linux and the example shown below is how the
code is
implemented on Unix.
The example included executed correctly on :
mandrake - ? (Can't remember, but it was an old version)
but fails to work on:
redhat - 2.2.14-5.0
debian - 2.2.9
mandrake - 2.4.19-16mdk
We are currently working on mandrake - kernel 2.4.19-16mdk.
Dirk
-------------------------------------------------------------------------------
Example program:
-------------------------------------------------------------------------------
#include <stdio.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <errno.h>
#define SHM_MODE (SHM_R | SHM_W)
union {
long IN[2048];
} global01_ __attribute__ ((aligned(4096)));
int main(void) {
int shmid;
char *shmptr;
if ( (shmid = shmget(IPC_PRIVATE, sizeof(global01_), SHM_MODE)) < 0){
printf("shmget error: %d %s\n",errno, strerror(errno));
exit(0);
}
if ( (shmptr = shmat(shmid, &global01_, SHM_RND)) == (void *) -1)
printf("shmat error: %d %s\n",errno, strerror(errno));
else
printf("shared memory attached from %x to %x\n",
shmptr, shmptr+sizeof(global01_));
if (shmctl(shmid, IPC_RMID, 0) < 0)
printf("shmctl error: %d %s\n",errno, strerror(errno));
exit(0);
}
_________________________________________________________________
Protect your PC - get McAfee.com VirusScan Online
http://clinic.mcafee.com/clinic/ibuy/campaign.asp?cid=3963
"Dirk Bull" <[email protected]> writes:
> Doug, thanks for the reply. I've set SHM_RND in the call and used
> "__attribute__ ((aligned(4096)))" during the the declaration of
> variable global01_
> (as shown below) such that it is aligned on a page boundary. I'm
> porting code that was
> written for a Unix system to Linux and the example shown below is how
> the code is
> implemented on Unix.
Hmmm, I may be ignorant, but I don't see how the below could work.
You're asking for the kernel to map your shared memory in the middle
of an already-mapped area (the bss segment). I'm actually surprised
it works on any Unix.
If you can point out a clear violation of the POSIX spec, someone may
be willing to change it, but it's not clear to me that you're
guaranteed to be able to map a shared memory area inside your existing
data segment.
> union {
> long IN[2048];
> } global01_ __attribute__ ((aligned(4096)));
[...]
> if ( (shmptr = shmat(shmid, &global01_, SHM_RND)) == (void *) -1)
> printf("shmat error: %d %s\n",errno, strerror(errno));
> else
> printf("shared memory attached from %x to %x\n",
> shmptr, shmptr+sizeof(global01_));
-Doug
On 6 Jan 2003, Doug McNaught wrote:
> "Dirk Bull" <[email protected]> writes:
>
> > Doug, thanks for the reply. I've set SHM_RND in the call and used
> > "__attribute__ ((aligned(4096)))" during the the declaration of
> > variable global01_
> > (as shown below) such that it is aligned on a page boundary. I'm
> > porting code that was
> > written for a Unix system to Linux and the example shown below is how
> > the code is
> > implemented on Unix.
>
> Hmmm, I may be ignorant, but I don't see how the below could work.
> You're asking for the kernel to map your shared memory in the middle
> of an already-mapped area (the bss segment). I'm actually surprised
> it works on any Unix.
>
> If you can point out a clear violation of the POSIX spec, someone may
> be willing to change it, but it's not clear to me that you're
> guaranteed to be able to map a shared memory area inside your existing
> data segment.
>
> > union {
> > long IN[2048];
> > } global01_ __attribute__ ((aligned(4096)));
>
> [...]
>
> > if ( (shmptr = shmat(shmid, &global01_, SHM_RND)) == (void *) -1)
> > printf("shmat error: %d %s\n",errno, strerror(errno));
> > else
> > printf("shared memory attached from %x to %x\n",
> > shmptr, shmptr+sizeof(global01_));
>
> -Doug
You beat me to the answer. I was re-writing this to use a pointer,
not an already allocated data object that exists in the .bss section.
This was to show how it's usually done. Basically, SHM_RND may round
down so, with odd-sized mapping, you have to be careful.
Since I did not think it should work, I tried first to initialize
global01_, which would put it into the .data section. This didn't
work either so I don't think the demo code is supposed to work.
Cheers,
Dick Johnson
Penguin : Linux version 2.4.18 on an i686 machine (797.90 BogoMips).
Why is the government concerned about the lunatic fringe? Think about it.
> Doug, thanks for the reply. I've set SHM_RND in the call and used
> "__attribute__ ((aligned(4096)))" during the the declaration of variable
> global01_
> (as shown below) such that it is aligned on a page boundary. I'm porting
> code that was
> written for a Unix system to Linux and the example shown below is how the
> code is implemented on Unix.
on which exactly?
> The example included executed correctly on:
> mandrake - ? (Can't remember, but it was an old version)
>
> but fails to work on:
> redhat - 2.2.14-5.0
> debian - 2.2.9
> mandrake - 2.4.19-16mdk
>
> We are currently working on mandrake - kernel 2.4.19-16mdk.
You have to add SHM_REMAP to shmat flags (see definitions of SHM_ flags).
>
> if ( (shmptr = shmat(shmid, &global01_, SHM_RND)) == (void *) -1)
> printf("shmat error: %d %s\n",errno, strerror(errno));
> else
add SHM_REMAP.
-alex
Alex Riesen <[email protected]> writes:
> You have to add SHM_REMAP to shmat flags (see definitions of SHM_ flags).
Hmm, the manpage (on RH7.3 at least) doesn't mention SHM_REMAP. Nice
to know about it.
-Doug
Doug McNaught, Mon, Jan 06, 2003 17:36:39 +0100:
> > You have to add SHM_REMAP to shmat flags (see definitions of SHM_ flags).
> Hmm, the manpage (on RH7.3 at least) doesn't mention SHM_REMAP. Nice
> to know about it.
RH7.3 manpage is quiet old, btw.
Linux manpages-1.54 (Dec 30 2002):
The (Linux-specific) SHM_REMAP flag may be asserted in shmflg to indi-
cate that the mapping of the segment should replace any existing map-
ping in the range starting at shmaddr and continuing for the size of
the segment. (Normally an EINVAL error would result if a mapping
already exists in this address range.) In this case, shmaddr must not
be NULL.
-alex
Alex Riesen <[email protected]> writes:
> Doug McNaught, Mon, Jan 06, 2003 17:36:39 +0100:
> > > You have to add SHM_REMAP to shmat flags (see definitions of SHM_ flags).
> > Hmm, the manpage (on RH7.3 at least) doesn't mention SHM_REMAP. Nice
> > to know about it.
>
> RH7.3 manpage is quiet old, btw.
Apparently so.
> Linux manpages-1.54 (Dec 30 2002):
>
> The (Linux-specific) SHM_REMAP flag may be asserted in shmflg to indi-
> cate that the mapping of the segment should replace any existing map-
> ping in the range starting at shmaddr and continuing for the size of
> the segment. (Normally an EINVAL error would result if a mapping
> already exists in this address range.) In this case, shmaddr must not
> be NULL.
Wouldn't the OP's code still (potentially) have problems? What if you
had:
char my_shared_area[2048];
int my_unshared_var;
...
void *foo = shmat(id, &my_shared_area, SHM_REMAP);
Would my_unshared_var end up shared, since memory mappings have page
granularity?
-Doug
Doug McNaught, Mon, Jan 06, 2003 17:50:24 +0100:
> > Linux manpages-1.54 (Dec 30 2002):
> >
> > The (Linux-specific) SHM_REMAP flag may be asserted in shmflg to indi-
> > cate that the mapping of the segment should replace any existing map-
> > ping in the range starting at shmaddr and continuing for the size of
> > the segment. (Normally an EINVAL error would result if a mapping
> > already exists in this address range.) In this case, shmaddr must not
> > be NULL.
>
> Wouldn't the OP's code still (potentially) have problems? What if you
> had:
>
> char my_shared_area[2048];
> int my_unshared_var;
>
> void *foo = shmat(id, &my_shared_area, SHM_REMAP);
>
> Would my_unshared_var end up shared, since memory mappings have page
> granularity?
>
yes, i suppose so.
Maybe that was the reason making SHM_REMAP non-default
behaviour for shmat.
-alex
Thanks for your help. I also thought the memory mapping code I'm
porting looked funny. The code forms part of a simulation program where a
few processes have to share data in a data base. In the code they(the
original implementers) initialize a bunch of variables and then share these
variables as I've shown you. I've referenced W.R Stevens's UNIX programming
books and found no information on whether you could share memory other than
that on the heap (did not want to change their code to use pointers, not a
good idea to change too much of the original code). To end a long story,
Alex, thanks for the SHM_REMAP flag, would never have found it, you've saved
me a lot of time. Finally, in the code they share pages, therefor using
SHM_REMAP is not that unsafe, but still not good practice?
Thanks again.
Dirk
_________________________________________________________________
Help STOP SPAM: Try the new MSN 8 and get 2 months FREE*
http://join.msn.com/?page=features/junkmail
Dirk Bull, Tue, Jan 07, 2003 09:14:17 +0100:
> saved me a lot of time. Finally, in the code they share pages, therefor
> using SHM_REMAP is not that unsafe, but still not good practice?
it seems correctly implemented, but the approach is error-prone
(Doug McNaught pointed on that).
What would you do if pagesize change? Fixing the code again
maybe a painful way, if the remapping was made to a common
practice.
-alex