Map a memory region into a process's address space
#include <sys/mman.h>
void * mmap( void * addr,
size_t len,
int prot,
int flags,
int fildes,
off_t off );
void * mmap64( void * addr,
size_t len,
int prot,
int flags,
int fildes,
off64_t off );
- addr
- NULL, or a pointer to where you want the object to be mapped
in the calling process's address space.
- len
- The number of bytes to map into the caller's address space. It can't be 0.
- prot
- The access capabilities that you want to use for the memory region being
mapped.
You can combine at least the following protection bits, as defined in
<sys/mman.h>:
- PROT_EXEC -- the region can be executed.
- PROT_NOCACHE -- disable caching of the region
(e.g. so it can be used to access dual-ported memory).
- PROT_NONE -- the region can't be accessed.
- PROT_READ -- the region can be read.
- PROT_WRITE -- the region can be written.
- flags
- Flags that specify further information about handling the mapped region;
see below.
- fildes
- The file descriptor for a shared memory object, or NOFD
if you're mapping physical memory.
- off
- The offset into shared memory of the location that you want to start
mapping.
libc
Use the -l c option to
qcc
to link against this library.
This library is usually included automatically.
The mmap() function maps
a region within the object beginning at off and
continuing for len into the caller's address space and returns
the location.
Typically, you don't need to use addr; you can just pass
NULL instead.
If you set addr to a non-NULL value, whether the object
is mapped depends on whether or not you set MAP_FIXED in
flags:
- MAP_FIXED is set
- The object is mapped to the address in addr, or the function fails.
- MAP_FIXED isn't set
- The value of addr is taken as a hint as to where to
map the object
in the calling process's address space.
The mapped area won't overlay any current mapped areas.
There are two parts to the flags parameter.
The first part is a type (masked by the MAP_TYPE bits),
which you must specify as one of the following:
- MAP_PRIVATE
- The mapping is private to the calling process.
It allocates system RAM and copies the current object.
- MAP_SHARED
- The mapping may be shared by many processes.
You can OR the following flags into the above type to further specify the
mapping:
- MAP_ANON
- This is most commonly used with MAP_PRIVATE. The fildes parameter must be NOFD.
The allocated memory is zero-filled.
This is equivalent to opening /dev/zero.
- MAP_BELOW16M
- Used with MAP_PHYS | MAP_ANON.
The allocated memory area resides in physical memory below 16M.
This is important for using DMA with ISA bus devices.
- MAP_FIXED
- Map the object to the address specified by addr.
If this area is already mapped, the call changes the existing mapping of the area.
|
Use MAP_FIXED with caution.
Not all memory models support it.
In general, you should assume that you can MAP_FIXED
only at an address (and size) that a call to
mmap() without MAP_FIXED returned.
|
A memory area being mapped with MAP_FIXED is first unmapped
by the system using the same memory area.
See
munmap()
for details.
- MAP_LAZY
- Delay acquiring system memory, and copying or zero-filling the
MAP_PRIVATE or MAP_ANON pages,
until an access to the area has occurred.
If you set this flag, and there's no system memory at the time of the access,
the thread gets a SIGBUS with a code of
BUS_ADRERR.
This flag is a hint to the memory manager.
- MAP_PHYS
- Physical memory is required.
The fildes parameter must be NOFD.
When used with MAP_PRIVATE or MAP_SHARED,
the offset specifies the exact physical address to map (e.g. for video frame buffers),
and is equivalent to opening /dev/mem.
If used with MAP_ANON, then physically contiguous memory is allocated.
MAP_NOX64K and MAP_BELOW16M are used to
further define the MAP_ANON allocated memory (useful on x86 only).
- MAP_NOINIT
- When specified, the POSIX requirement that the memory be zeroed is
relaxed.
The physical memory being used for this allocation must have been
previously freed with UNMAP_INIT_OPTIONAL for this flag
to have any effect.
|
This flag was added in the QNX Neutrino Core OS 6.3.2. |
- MAP_NOX64K
- (Useful on x86 only).
Used with MAP_PHYS | MAP_ANON.
Prevent the allocated memory area from crossing a 64K boundary.
This may be important to some DMA devices.
If more than 64K is requested, the area begins on a 64K boundary.
- MAP_STACK
- This flag tells the memory allocator what the MAP_ANON memory will be used for.
It's only a hint.
Using the mapping flags described above, a process can easily share memory between processes:
/* Map in a shared memory region */
fd = shm_open( "/datapoints", O_RDWR, 0777 );
addr = mmap( 0, len, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0 );
To share memory with hardware such as video memory on an x86 platform:
/* Map in VGA display memory */
addr = mmap( 0,
65536,
PROT_READ|PROT_WRITE,
MAP_PHYS|MAP_SHARED,
NOFD,
0xa0000 );
To allocate a DMA buffer for a bus-mastering PCI network card:
/* Allocate a physically contiguous buffer */
addr = mmap( 0,
262144,
PROT_READ|PROT_WRITE|PROT_NOCACHE,
MAP_PHYS|MAP_ANON,
NOFD,
0 );
The address of the mapped-in object,
or MAP_FAILED if an error occurred
(errno is set).
- EACCES
- The file descriptor in fildes isn't open for reading,
or you specified PROT_WRITE and MAP_SHARED,
and fildes isn't open for writing.
- EBADF
- Invalid file descriptor, fildes.
- EINVAL
- Invalid flags type, or len is 0.
- ENODEV
- The fildes argument refers to an object for which mmap() is meaningless (e.g. a terminal).
- ENOMEM
- You specified MAP_FIXED, and the address range requested
is outside of the allowed process address range, or
there wasn't enough memory to satisfy the request.
- ENXIO
- The address from off for len bytes is invalid for the requested object,
or you specified MAP_FIXED, and addr,
len, and off
are invalid for the requested object.
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <errno.h>
#include <stdlib.h>
#include <sys/mman.h>
int main(int argc, char *argv[])
{
int i;
unsigned char *addr, c;
/* Map BIOS ROM */
addr = mmap(0, 0x10000, PROT_READ | PROT_WRITE,
MAP_SHARED | MAP_PHYS, NOFD, 0xf0000);
if (addr == MAP_FAILED) {
fprintf(stderr, "mmap failed : %s\n",
strerror(errno));
return EXIT_FAILURE;
}
printf("Map addr is %p\n",(void*) addr);
for (i = 0; i < 3 * 80; ++i) {
c = *addr++;
if (c >= ' ' && c <= 0x7f)
putchar(c);
else
putchar('.');
}
return EXIT_SUCCESS;
}
mmap() is
POSIX 1003.1 MF|SHM|TYM;
mmap64() is
Large-file support
Safety: | |
Cancellation point |
No |
Interrupt handler |
No |
Signal handler |
Yes |
Thread |
Yes |
mmap_device_io(),
mmap_device_memory(),
munmap()