#include <sys/types.h> #include <sys/mman.h> void *mmap( void *addr, size_t len, int protection, int flags, int fildes, off_t off);Service Program Name: QP0LLIB1
The mmap() function establishes a mapping between a process' address space and a stream file.
The address space of the process from the address returned to the caller, for a length of len, is mapped onto a stream file starting at offset off.
The portion of the stream file being mapped is from starting offset off for a length of len bytes. The actual address returned from the function is derived from the values of flags and the value specified for address.
The mmap() function causes a reference to be associated with the file represented by fildes. This reference is not removed by subsequent close operations. The file remains referenced as long as a mapping exists over the file.
If a mapping already exists for the portion of the processes address space that is to be mapped and the value MAP_FIXED was specified for flags, then the previous mappings for the affected pages are implicitly unmapped. If one or more files affected by the implicit unmap no longer have active mappings, these files will be unreferenced as a result of mmap().
The use of the mmap() function is restricted by the QSHRMEMCTL System Value. When this system value is 0, the mmap() function may not create a shared mapping having with PROT_WRITE capability. Essentially, this prevents the creation of a memory map that could alter the contents of the stream file being mapped. If the flags parameter indicated MAP_SHARED, the prot parameter specifies PROT_WRITE and the QSHRMEMCTL system value is 0, then the mmap() functions will fail and an error number of EACCES results.
When the mmap() function creates a memory map, the current value of the QSHRMEMCTL system value is stored with the mapping. This further restricts attempts to change the protection of the mapping through the use of the mprotect function. Changing the system valueonly affects memory maps created after the system value is changed.
If the size of the file increases after the mmap() function completes, then the whole pages beyond the original end of file will not be accessible via the mapping.
If the size of the mapped file is decreased after mmap(), attempts to reference beyond the end of the file are undefined and may result in an MCH0601 exception.
Any data written to that portion of the file that is allocated beyond end-of-file may not be preserved. Changes made beyond end of file via mapped access may not be preserved.
The portion of the file beyond end-of-file is assumed to be zero by the traditional file access APIs such as read(), readv(), write(), writev(), and ftruncate(). The system may clear a partial page, or whole pages allocated beyond end-of-file. This must be taken into account when directly changing a memory mapped file beyond end-of-file. It is not recommended that data be directly changed beyond end-of-file because the extra space allocated varies and unpredictable results may occur.
The mmap() function is only supported for *TYPE2 stream files (*STMF) existing in the "root" (/), QOpenSys, and user-defined file systems.
Journaling cannot be started while a file is memory mapped. Likewise, a journaled file cannot be memory mapped. The mmap() function will fail with ENOTSUP if the file is journaled.
The off parameter must be zero or a multiple of the system page size. The _SC_PAGESIZE or _SC_PAGE_SIZE options on the sysconf() function may be used to retrieve the system page size.
The PROT_WRITE value requires that the file be opened for write and read access.
The following table shows the symbolic constants allowed for the protection parameter.
Symbolic Constant | Decimal Value |
Description |
---|---|---|
PROT_READ | 1 | Read access is allowed. |
PROT_WRITE | 2 | Write access is allowed. Note that this value assumes PROT_READ also. |
PROT_NONE | 8 | No data access is allowed. |
PROT_EXEC | 4 | This value is allowed, but is equivalent to PROT_READ. |
The first attribute controls whether or not changes made through the mapping will be seen by other processes. The MAP_PRIVATE option will cause a copy on write mapping to be created. A change to the mapping results in a change to a private copy of the affected portion of the file. These changes cannot be seen by other processes. The MAP_SHARED option provides a memory mapping of the file where changes (if allowed by the protection parameter) are made to the file. Changes are shared with other processes when MAP_SHARED is specified.
The second control provided by the flags parameter in conjunction with the value of the addr parameter influences the address range assigned to the mapping. You may request one of the following address selection modes:
The MAP_FIXED flag value specifies that the virtual address has been specified through the addr parameter. The mmap() function will use the value of addr as the starting point of the memory map.
When MAP_FIXED is set in the flags parameter, the system is informed that the return value must be equal to the value of addr. An invalid value of addr when MAP_FIXED is specified will result in a value of MAP_FAILED, which has a value of 0, for the returned value and the the value of errno will be set to EINVAL.
When MAP_FIXED is not specified, a value of zero for parameter addr indicates that the system may choose the value for the return value. If MAP_FIXED is not specified and a nonzero value is specified for addr, the system will take this as a suggestion to find a contiguous address range close to the specified address.
The following table shows the symbolic constants allowed for the flags parameter.
Symbolic Constant | Decimal Value |
Description |
---|---|---|
MAP_SHARED | 4 | Changes are shared. |
MAP_PRIVATE | 2 | Changes are private. |
MAP_FIXED | 1 | Parameter addr has exact address |
No authority checking is performed by the mmap() function because this was done by the open() functions which assigned the file descriptor, fildes, used by the mmap() function.
The following table shows the open access intent that is required for the various combinations of the mapping sharing mode and mapping intent.
Mapping Sharing Mode | Mapping Intent | Open access intents allowed |
---|---|---|
MAP_SHARED | PROT_READ | O_RDONLY or O_RDWR |
MAP_SHARED | PROT_WRITE | O_RDWR |
MAP_SHARED | PROT_NONE | O_RDONLY or O_RDWR |
MAP_PRIVATE | PROT_READ | O_RDONLY or O_RDWR |
MAP_PRIVATE | PROT_WRITE | O_RDONLY or O_RDWR |
MAP_PRIVATE | PROT_NONE | O_RDONLY or O_RDWR |
Upon successful completion, the mmap() function returns the address at which the mapping was placed; otherwise, it returns a value of MAP_FAILED, which has a value of 0, and sets errno to indicate the error. The symbol MAP_FAILED is defined in the header <sys/mman.h>.
If successful, function mmap() will never return a value of MAP_FAILED.
If mmap() fails for reasons other than EBADF, EINVAL, or ENOTSUP, some of the mappings in the address range starting at addr and continuing for len bytes may have been unmapped and no new mappings are created.
When the mmap() function fails, it returns MAP_FAILED, which has a value of 0, and sets the errno as follows.
Error condition | Additional information |
---|---|
[EACCES] |
If you are accessing a remote file through the Network File System, update operations to file permissions at the server are not reflected at the client until updates to data that is stored locally by the Network File System take place. (Several options on the Add Mounted File System (ADDMFS) command determine the time between refresh operations of local data.) Access to a remote file may also fail due to different mappings of user IDs (UID) or group IDs (GID) on the local and remote systems. The file referenced by fildes is not open for read, or the file is not opened for write and PROT_WRITE for a shared mapping is being requested. This error also results when the QSHRMEMCTL system value is 0 and PROT_WRITE is specified. |
[EBADFUNC] |
A given file descriptor or directory pointer is not valid for this operation. The specified descriptor is incorrect, or does not refer to an open file. |
[EINVAL] |
The value of the addr parameter is not valid. This can occur when MAP_FIXED is specified and the value of the addr parameter is not a multiple of the system page size. This may also occur if the value for parameter addr is not a valid VOID* pointer or is not within the range allowed. This error number is also returned if the value of the flags parameter does not indicate either MAP_SHARED or MAP_PRIVATE. |
[ENODEV] |
The fildes parameter does not refer to a *TYPE2 stream file (*STMF) in the "root" (/), QOpenSys, or user-defined file systems. |
[ENOMEM] |
This can occur if the portion of the local process address space reserved for memory mapping has been exceeded. When MAP_FIXED is specified, it may also occur if the address range specified by the combination of the addr and len parameters results in a range outside the range reserved for process local storage. |
[ENOTAVAIL] | |
[ENOTSUP] | |
[ENXIO] |
The portion of the file, as specified by off and len is not valid for the current size of the file. |
[EOVERFLOW] | |
[EUNKNOWN] |
The following messages may be sent from this function.
Message ID | Error Message Text |
---|---|
CPE3418 E | Possible APAR condition or hardware failure. |
CPFA0D4 E | File system error occurred. |
CPF3CF2 E | Error(s) occurred during running of &1 API. |
CPF9872 E | Program or service program &1 in library &2 ended. Reason code &3. |
If the DTAMDL(*LLP64) parameter is used when compiling an ILE C program, this limitation does not apply as the pointers will be 8 byte pointers, and their pointer attribute will be preserved.
See Code disclaimer information for information pertaining to code examples.
The following example creates two files and then produces a contiguous memory mapping of the first data page of each file using two invocations of mmap().
#include <errno.h> #include <fcntl.h> #include <unistd.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/types.h> #include <sys/mman.h> main(void) { size_t bytesWritten = 0; int my_offset = 0; char text1Ý="Data for file 1."; char text2Ý="Data for file 2."; int fd1,fd2; int PageSize; void *address; void *address2; fd1 = open("/tmp/mmaptest1", (O_CREAT | O_TRUNC | O_RDWR), (S_IRWXU | S_IRWXG | S_IRWXO) ); if ( fd1 < 0 ) perror("open() error"); else { bytesWritten = write(fd1, text1, strlen(text1)); if ( bytesWritten != strlen(text1) ) { perror("write() error"); int closeRC = close(fd1); return -1; } fd2 = open("/tmp/mmaptest2", (O_CREAT | O_TRUNC | O_RDWR), (S_IRWXU | S_IRWXG | S_IRWXO) ); if (fd2 < 0 ) perror("open() error"); else { bytesWritten = write(fd2, text2, strlen(text2)); if ( bytesWritten != strlen(text2) ) perror("write() error"); PageSize = (int)sysconf(_SC_PAGESIZE); if ( PageSize < 0) { perror("sysconf() error"); } else { off_t lastoffset = lseek( fd1, PageSize-1, SEEK_SET); if (lastoffset < 0 ) { perror("lseek() error"); } else { bytesWritten = write(fd1, " ", 1); /* grow file 1 to 1 page. */ off_t lastoffset = lseek( fd2, PageSize-1, SEEK_SET); bytesWritten = write(fd2, " ", 1); /* grow file 2 to 1 page. */ /* * We want to show how to memory map two files with * the same memory map. We are going to create a two page * memory map over file number 1, even though there is only * one page available. Then we will come back and remap * the 2nd page of the address range returned from step 1 * over the first 4096 bytes of file 2. */ int len; my_offset = 0; len = PageSize; /* Map one page */ address = mmap(NULL, len, PROT_READ, MAP_SHARED, fd1, my_offset ); if ( address != MAP_FAILED ) { address2 = mmap( ((char*)address)+PageSize, len, PROT_READ, MAP_SHARED | MAP_FIXED, fd2, my_offset ); if ( address2 != MAP_FAILED ) { /* print data from file 1 */ printf("\n%s",address); /* print data from file 2 */ printf("\n%s",address2); } /* address 2 was okay. */ else { perror("mmap() error="); } /* mmap for file 2 failed. */ } else { perror("munmap() error="); } /* * Unmap two pages. */ if ( munmap(address, 2*PageSize) < 0) { perror("munmap() error"); } else; } } close(fd2); unlink( "/tmp/mmaptest2"); } close(fd1); unlink( "/tmp/mmaptest1"); } /* * Unmap two pages. */ if ( munmap(address, 2*PageSize) < 0) { perror("munmap() error"); } else; }Output:
Data for file 1 Data for file 2
Top | UNIX-Type APIs | APIs by category |