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 );
The following are Unix or QNX Neutrino extensions:
For more information, see below.
If you want to map a device's physical memory, use
mmap_device_memory()
instead of mmap().
On x86, if a device's registers are memory-mapped, you can use mmap_device_memory() to access them. Otherwise you can use mmap_device_io() to gain access to the device, and routines such as in8() and out8() to access them. On architectures other than the x86, both methods are equivalent. |
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 specified by filedes, beginning at off and continuing for len, into the caller's address space and returns the location. The object that you map from can be one of the following:
If fildes isn't NOFD, you must have opened the file descriptor for reading, no matter what value you specify for prot; write access is also required for PROT_WRITE if you haven't specified MAP_PRIVATE.
The mapping is as shown below.
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:
There are two parts to the flags parameter. The first part is a type (masked by the MAP_TYPE bits), which is maintained across a fork(). You must specify one of the following types:
You can OR the following flags into the above type to further specify the mapping:
MAP_ANON is most commonly used with MAP_PRIVATE, but you can use it with MAP_SHARED to create a shared memory area for forked applications.
You can have more than one writeable mapping to a file. If you access the file via file descriptors as well as via the memory mapping, you'll have to be careful to keep the file's contents coherent. For example, you should specify O_SYNC when you open() the file. |
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.
For anonymous shared memory objects (those created via mmap() with MAP_ANON | MAP_SHARED and a file descriptor of -1), a MAP_LAZY flag implicitly sets the SHMCTL_LAZY flag on the object (see shm_ctl()).
This flag was added in the QNX Neutrino Core OS 6.3.2. |
If the same region in a file is mapped twice, once with MAP_NOSYNCFILE and once without, the memory manager might not be able to tell whether a change was made through the MAP_NOSYNCFILE mapping or not, and thus write out changes that weren't intended. |
If you use MAP_PHYS with MAP_ANON, mmap() allocates physically contiguous memory and ignores the offset. You can use MAP_NOX64K and MAP_BELOW16M to further define the MAP_ANON allocated memory (useful on x86 only).
You should use mmap_device_memory() instead of MAP_PHYS, unless you're allocating physically contiguous memory. |
The following flags are defined in <sys/mman.h>, but you shouldn't use them:
Specifying the MAP_SYSRAM bit in a call to mmap() will result in an error of EINVAL. |
If fildes represents a typed memory object opened with either the POSIX_TYPED_MEM_ALLOCATE or POSIX_TYPED_MEM_ALLOCATE_CONTIG flag (see posix_typed_mem_open()), and there are enough resources available, mmap() maps len bytes allocated from the corresponding typed memory object that weren't previously allocated to any process in any processor that may access that typed memory object. If there aren't enough resources available, mmap() fails.
If fildes represents a typed memory object opened with the POSIX_TYPED_MEM_ALLOCATE_CONTIG flag, the allocated bytes are contiguous within the typed memory object. If the typed memory object wase opened with POSIX_TYPED_MEM_ALLOCATE, the allocated bytes may be composed of noncontiguous fragments within the typed memory object. If the typed memory object was opened with neither of these flags, len bytes starting at the given offset within the typed memory object are mapped, exactly as when mapping a file or shared memory object. In this case, if two processes map an area of typed memory using the same offset and length and using file descriptors that refer to the same memory pool (either from the same port or from a different port), both processes map the same region of storage.
The address of the mapped-in object, or MAP_FAILED if an error occurred (errno is set).
Open a shared memory object and share it with other processes:
fd = shm_open( "/datapoints", O_RDWR, 0777 ); addr = mmap( 0, len, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0 );
Allocate a physically contiguous DMA buffer for a bus-mastering PCI network card:
addr = mmap( 0, 262144, PROT_READ|PROT_WRITE|PROT_NOCACHE, MAP_PHYS|MAP_ANON, NOFD, 0 );
Map a file into memory, change the memory, and then verify that the file's contents have been updated:
#include <stdlib.h> #include <stdio.h> #include <sys/mman.h> #include <fcntl.h> #include <unistd.h> #include <string.h> #define TESTSTRING "AAAAAAAAAA" int main(int argc, char *argv[]) { char buffer[80], filename[200] = "/tmp/try_it"; int fd, file_size, ret, size_written, size_read; void *addr; /* Write the test string into the file. */ unlink( filename); fd = open( filename, O_CREAT|O_RDWR , 0777 ); if( fd == -1) { perror("open"); exit(EXIT_FAILURE); } size_written = write( fd, TESTSTRING, sizeof (TESTSTRING) ); if ( size_written == -1 ){ perror("write"); exit(0); } printf( "Wrote %d bytes into file %s\n", size_written, filename ); lseek( fd, 0L, SEEK_SET ); file_size = lseek( fd, 0L, SEEK_END ); printf( "Size of file = %d bytes\n", file_size ); /* Map the file into memory. */ addr = mmap( 0, file_size, PROT_READ | PROT_WRITE , MAP_SHARED, fd, 0 ); if (addr == MAP_FAILED) { perror("mmap"); exit(EXIT_FAILURE); } /* Change the memory and synchronize it with the disk. */ memset( addr, 'B', 5 ); ret = msync( addr, file_size, MS_SYNC); if( ret == -1) { perror("msync"); exit(0); } /* Close and reopen the file, and then read its contents. */ close(fd); fd = open( filename, O_RDONLY); if( fd == -1) { perror("open"); exit(EXIT_FAILURE); } size_read = read( fd, buffer, sizeof( buffer ) ); printf( "File content = %s\n", buffer ); close(fd); 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(), msync(), posix_typed_mem_open(), setrlimit(), shm_open()
“Shared memory” and “Typed memory” in the Interprocess Communication (IPC) chapter of the System Architecture guide