Reputation: 329
For a project I have to do I have to use:
void *ptr = mmap(NULL, N, PROT_READ|PROT_WRITE, MAP_SHARED|MAP_ANONYMOUS, 0, 0);
where N
is the number of bytes of RAM to ask for from the OS.
When this statement executes, what is ptr
pointing to? Is it pointing to the start of the shared memory between processes? Also, if in this memory space say I want to store 1,000 int
pointers, do I need to have N = 1000 * sizeof(int *);
?
And assuming that I am correct, where is the second place in memory that I can store something? Is it at ptr + 1
or ptr + 4
because an int *
is 4 bytes on a 32-bit system?
Thank I appreciate it.
Upvotes: 3
Views: 3725
Reputation: 162164
void *ptr = mmap( NULL, N, PROT_READ|PROT_WRITE, MAP_SHARED|MAP_ANONYMOUS, 0, 0);
where N is the number of bytes of RAM to ask for from the OS.
Here's one important constraint you must follow: N
must be an integer multiple of the system's page size (or if mapping hugepages, an integer multiple of a hugepage's size). Usually it's 4096 bytes, but the actual value is reported by sysconf(PAGESIZE)
.
When this statement executes, what is ptr pointing to?
The beginning of the portion of the address space this particular mapping has been created at. With a non-anonymous mapping you can map the same memory several times at different addresses (this is a neat trick to implement transparent ringbuffers).
Is it pointing to the start of the shared memory between processes?
At this particular point, it's just pointing to some memory. There's nothing shared about this yet. The mapping however will be shared after a fork
(or a clone
with the right flags); this already is process shared memory, but you probably will want to also execve
into a different executable.
Also, if in this memory space say I want to store 1,000 int pointers, do I need to have N = 1000 * sizeof(int *);?
Well, technically you need to have n * sysconf(PAGESIZE) == N >= 1000 * sizeof(int*)
; however why do you want to share int pointers? Unless you have those pointers point into (another) shared memory region, that's at the same address in every process that uses those pointers, it's pretty useless to share pointers. Of course after a fork
the address space of the processes is identical, but a execve
will unmap all previous mappings, and you'd have to use non-anonymous mmap
with MAP_FIXED
and a filedescriptor obtained with, e.g., memfd_create
, and use the first parameter of mmap
where exactly to map it at (which might fail, or overmap a previously existing mapping).
What you can sensibly share is offsets and bulk data.
Oh, and just to eliminate any confusion: Placing a pointer in a shared memory region will not automagically share the memory it's pointing to.
And assuming that I am correct, where is the second place in memory that I can store something? Is it at ptr + 1 or ptr + 4 because an int * is 4 bytes on a 32-bit system?
It's just plain memory, that you can use, as if it were allocated with malloc
. Cast the pointer to whatever type you see fit and use it as usual.
Upvotes: 1
Reputation: 861
Since mmap
is not defined in standard C, I'm assuming you're using this: http://linux.die.net/man/2/mmap
The return value is a pointer to the memory:
On success, mmap() returns a pointer to the mapped area. On error, the value MAP_FAILED (that is, (void *) -1) is returned, and errno is set appropriately. On success, munmap() returns 0, on failure -1, and errno is set (probably to EINVAL).
You are calculating N correctly.
However, you'll probably have problems using addition with a void*
pointer, so cast your pointer to an int*
to do addition.
int* p = ptr;
int* nextP = p + 1;
Upvotes: 1