3

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.

4
  • Yes, yes and at ((int*) ptr)[1] (which is equivalent to *(((int*) ptr) + 1)) Commented Oct 4, 2014 at 22:10
  • 2
    Are you sure you want to mmap() a standard io stream? I'd recommend mmap(NULL, N, flags, flags, -1, 0), personally. Commented Oct 4, 2014 at 22:13
  • This is what my instructor gave us to use to map a region of region between shared processes @EOF Commented Oct 4, 2014 at 22:19
  • Yeah, on Linux just using MAP_ANONYMOUS effectively implies fd = -1, but for portability you shouldn't write fd = 0. When in doubt, read the manpage. Commented Oct 4, 2014 at 22:25

2 Answers 2

1

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; 
Sign up to request clarification or add additional context in comments.

Comments

1
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.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.