Linux system calls mmap/munmap

prototype

#include <sys/mman.h>
void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset);
int munmap(void *addr, size_t length);

mmap

  1. Creates a memory-mapped region in the virtual memory space of the process calling this function.
  2. addr specifies the starting position of the memory map, if it is NULL, the kernel is responsible for allocation (page size alignment).
    Use NULL for good portability.
  3. When addr is not NULL, the kernel uses this value as a suggested value (hint).
    On Linux, the space near the edge of the page will be selected to create the mapping (always greater than or equal to the value specified in /proc/sys/vm/mmap_min_addr).
  4. If there is already a mapping at the location specified by addr, the kernel will choose a new address (not necessarily related to addr).
  5. The return value is the address of the created memory map.
  6. The content of the file memory map (file mapping, as opposed to anonymous mapping), is initialized with the object content specified by fd. The content starts from offset (integer multiple of pagesize, sysconf(_SC_PAGE_SIZE)), and the length is length.
  7. mmap has returned, fd can be closed.
  8. prot (protection) specifies the protection mode of the memory map (it cannot conflict with the open mode of the file).
    The optional value is prot_none or other values ​​for OR.
    PROT_EXEC, PROT_READ, PROT_WRITE, PROT_NONE
  9. flags parameter:
    1) This parameter affects the modification of the memory mapping content, whether it is visible to other processes (mapping the same memory area) or the mapped file.
    2)
    MAP_SHARED: The modification of the memory map is visible to other processes and underlying files, and unknown flags are ignored.
    MAP_SHARED_VALIDATE (since Linux 4.15, Linux extension), is the same as MAP_SHARED except that an error will be reported when encountering unknown flags. Use with MAP_SYNC to avoid data loss when the system crashes.
    MAP_PRIVATE: Modifications to the memory map are invisible to other processes and to underlying files.
    MAP_ANONYMOUS: No need to map a file, the memory area is initialized to 0. fd can be ignored, set to -1 for compatibility (required on some systems).
    MAP_FIXE: It is mandatory to map to the address specified by addr (addr must be page aligned). Due to the different memory layouts of different versions of kernel, libc, etc., use this option with caution!
    MAP_NORESERVE: Do not reserve swap space for memory mapping. Writes to memory maps encounter SIGSEGV errors when physical memory is exhausted.

unmap

  1. Delete the memory mapping specified by addr, and all references to addresses within the memory mapping range will become invalid.
  2. When the process ends, the memory map will be automatically unmapped.
  3. addr must be page size aligned, length has no such requirement.
  4. Return value: success - 0, failed - -1 (errno).

Demo

#include <sys/mman.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

#define handle_error(msg) \
    do {
      
       perror(msg); exit(EXIT_FAILURE); } while (0)

int
main(int argc, char *argv[])
{
    
    
    char *addr;
    int fd;
    struct stat sb;
    off_t offset, pa_offset;
    size_t length;
    ssize_t s;

    if (argc < 3 || argc > 4) {
    
    
        fprintf(stderr, "%s file offset [length]\n", argv[0]);
        exit(EXIT_FAILURE);
    }

    fd = open(argv[1], O_RDONLY);
    if (fd == -1)
        handle_error("open");

    if (fstat(fd, &sb) == -1)           /* To obtain file size */
        handle_error("fstat");

    offset = atoi(argv[2]);
    pa_offset = offset & ~(sysconf(_SC_PAGE_SIZE) - 1);
        /* offset for mmap() must be page aligned */

    if (offset >= sb.st_size) {
    
    
        fprintf(stderr, "offset is past end of file\n");
        exit(EXIT_FAILURE);
    }

    if (argc == 4) {
    
    
        length = atoi(argv[3]);
        if (offset + length > sb.st_size)
            length = sb.st_size - offset;
                /* Can't display bytes past end of file */

    } else {
    
        /* No length arg ==> display to end of file */
        length = sb.st_size - offset;
    }

    addr = mmap(NULL, length + offset - pa_offset, PROT_READ,
                MAP_PRIVATE, fd, pa_offset);
    if (addr == MAP_FAILED)
        handle_error("mmap");

    s = write(STDOUT_FILENO, addr + offset - pa_offset, length);
    if (s != length) {
    
    
        if (s == -1)
            handle_error("write");

        fprintf(stderr, "partial write");
        exit(EXIT_FAILURE);
    }

    munmap(addr, length + offset - pa_offset);
    close(fd);

    exit(EXIT_SUCCESS);
}

Guess you like

Origin blog.csdn.net/yinminsumeng/article/details/130886065