mmap手册见先关章节。本文主要介绍了 mmap 的原理和使用方式,通过本文我们可以知道,使用 mmap 对文件进行读写操作时可以减少内存拷贝的次数,并且可以减少系统调用的次数,从而提高对读写文件操作的效率。

由于内核不会主动同步 mmap 所映射的内存区中的数据,所以在某些特殊的场景下可能会出现数据丢失的情况(如断电)。为了避免数据丢失,在使用 mmap 的时候可以在适当时主动调用 msync 函数来同步映射内存区的数据。

目录

一、传统的读写文件

二、使用 mmap 读写文件

三、mmap的使用方式

四、mmap() manual

推荐阅读


一、传统的读写文件


一般来说,修改一个文件的内容需要如下3个步骤:

  • 把文件内容读入到内存中。
  • 修改内存中的内容。
  • 把内存的数据写入到文件中。

过程如图 1 所示:

如果使用代码来实现上面的过程,代码如下:

read(fd, buf, 1024);  // 读取文件的内容到buf...                   // 修改buf的内容
write(fd, buf, 1024); // 把buf的内容写入到文件

从图 1 中可以看出,页缓存(page cache) 是读写文件时的中间层,内核使用 页缓存 与文件的数据块关联起来。所以应用程序读写文件时,实际操作的是 页缓存

二、使用 mmap 读写文件


从传统读写文件的过程中,我们可以发现有个地方可以优化:如果可以直接在用户空间读写 页缓存,那么就可以免去将 页缓存 的数据复制到用户空间缓冲区的过程。

那么,有没有这样的技术能实现上面所说的方式呢?答案是肯定的,就是 mmap

使用 mmap 系统调用可以将用户空间的虚拟内存地址与文件进行映射(绑定),对映射后的虚拟内存地址进行读写操作就如同对文件进行读写操作一样。原理如图 2 所示:

前面我们介绍过,读写文件都需要经过 页缓存,所以 mmap 映射的正是文件的 页缓存,而非磁盘中的文件本身。由于 mmap 映射的是文件的 页缓存,所以就涉及到同步的问题,即 页缓存 会在什么时候把数据同步到磁盘。

Linux 内核并不会主动把 mmap 映射的 页缓存 同步到磁盘,而是需要用户主动触发。同步 mmap 映射的内存到磁盘有 4 个时机:

  • 调用 msync 函数主动进行数据同步(主动)。
  • 调用 munmap 函数对文件进行解除映射关系时(主动)。
  • 进程退出时(被动)。
  • 系统关机时(被动)。

三、mmap的使用方式


下面我们介绍一下怎么使用 mmapmmap 函数的原型如下:

void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset);

下面介绍一下 mmap 函数的各个参数作用:

  • addr:指定映射的虚拟内存地址,可以设置为 NULL,让 Linux 内核自动选择合适的虚拟内存地址。
  • length:映射的长度。
  • prot:映射内存的保护模式,可选值如下:
    • PROT_EXEC:可以被执行。
    • PROT_READ:可以被读取。
    • PROT_WRITE:可以被写入。
    • PROT_NONE:不可访问。
  • flags:指定映射的类型,常用的可选值如下:

    • MAP_FIXED:使用指定的起始虚拟内存地址进行映射。
    • MAP_SHARED:与其它所有映射到这个文件的进程共享映射空间(可实现共享内存)。
    • MAP_PRIVATE:建立一个写时复制(Copy on Write)的私有映射空间。
    • MAP_LOCKED:锁定映射区的页面,从而防止页面被交换出内存。
    • ...
  • fd:进行映射的文件句柄。
  • offset:文件偏移量(从文件的何处开始映射)。

介绍完 mmap 函数的原型后,我们现在通过一个简单的例子介绍怎么使用 mmap

int fd = open(filepath, O_RDWR, 0644);                           // 打开文件
void *addr = mmap(NULL, 8192, PROT_WRITE, MAP_SHARED, fd, 4096); // 对文件进行映射

在上面例子中,我们先通过 open 函数以可读写的方式打开文件,然后通过 mmap 函数对文件进行映射,映射的方式如下:

  • addr 参数设置为 NULL,表示让操作系统自动选择合适的虚拟内存地址进行映射。
  • length 参数设置为 8192 表示映射的区域为 2 个内存页的大小(一个内存页的大小为 4 KB)。
  • prot 参数设置为 PROT_WRITE 表示映射的内存区为可读写。
  • flags 参数设置为 MAP_SHARED 表示共享映射区。
  • fd 参数设置打开的文件句柄。
  • offset 参数设置为 4096 表示从文件的 4096 处开始映射。

mmap 函数会返回映射后的内存地址,我们可以通过此内存地址对文件进行读写操作。我们通过图 3 展示上面例子在内核中的结构:

四、mmap() manual


NAME

       mmap, munmap - map or unmap files or devices into memory

SYNOPSIS

       #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);
       See NOTES for information on feature test macro requirements.

DESCRIPTION

       mmap() creates a new mapping in the virtual address space of thecalling process.  The starting address for the new mapping isspecified in addr.  The length argument specifies the length ofthe mapping (which must be greater than 0).If addr is NULL, then the kernel chooses the (page-aligned)address at which to create the mapping; this is the most portablemethod of creating a new mapping.  If addr is not NULL, then thekernel takes it as a hint about where to place the mapping; onLinux, the kernel will pick a nearby page boundary (but alwaysabove or equal to the value specified by/proc/sys/vm/mmap_min_addr) and attempt to create the mappingthere.  If another mapping already exists there, the kernel picksa new address that may or may not depend on the hint.  Theaddress of the new mapping is returned as the result of the call.The contents of a file mapping (as opposed to an anonymousmapping; see MAP_ANONYMOUS below), are initialized using lengthbytes starting at offset offset in the file (or other object)referred to by the file descriptor fd.  offset must be a multipleof the page size as returned by sysconf(_SC_PAGE_SIZE).After the mmap() call has returned, the file descriptor, fd, canbe closed immediately without invalidating the mapping.The prot argument describes the desired memory protection of themapping (and must not conflict with the open mode of the file).It is either PROT_NONE or the bitwise OR of one or more of thefollowing flags:PROT_EXECPages may be executed.PROT_READPages may be read.PROT_WRITEPages may be written.PROT_NONEPages may not be accessed.The flags argumentThe flags argument determines whether updates to the mapping arevisible to other processes mapping the same region, and whetherupdates are carried through to the underlying file.  Thisbehavior is determined by including exactly one of the followingvalues in flags:MAP_SHAREDShare this mapping.  Updates to the mapping are visible toother processes mapping the same region, and (in the caseof file-backed mappings) are carried through to theunderlying file.  (To precisely control when updates arecarried through to the underlying file requires the use ofmsync(2).)MAP_SHARED_VALIDATE (since Linux 4.15)This flag provides the same behavior as MAP_SHARED exceptthat MAP_SHARED mappings ignore unknown flags in flags.By contrast, when creating a mapping usingMAP_SHARED_VALIDATE, the kernel verifies all passed flagsare known and fails the mapping with the error EOPNOTSUPPfor unknown flags.  This mapping type is also required tobe able to use some mapping flags (e.g., MAP_SYNC).MAP_PRIVATECreate a private copy-on-write mapping.  Updates to themapping are not visible to other processes mapping thesame file, and are not carried through to the underlyingfile.  It is unspecified whether changes made to the fileafter the mmap() call are visible in the mapped region.Both MAP_SHARED and MAP_PRIVATE are described in POSIX.1-2001 andPOSIX.1-2008.  MAP_SHARED_VALIDATE is a Linux extension.In addition, zero or more of the following values can be ORed inflags:MAP_32BIT (since Linux 2.4.20, 2.6)Put the mapping into the first 2 Gigabytes of the processaddress space.  This flag is supported only on x86-64, for64-bit programs.  It was added to allow thread stacks tobe allocated somewhere in the first 2 GB of memory, so asto improve context-switch performance on some early 64-bitprocessors.  Modern x86-64 processors no longer have thisperformance problem, so use of this flag is not requiredon those systems.  The MAP_32BIT flag is ignored whenMAP_FIXED is set.MAP_ANONSynonym for MAP_ANONYMOUS; provided for compatibility withother implementations.MAP_ANONYMOUSThe mapping is not backed by any file; its contents areinitialized to zero.  The fd argument is ignored; however,some implementations require fd to be -1 if MAP_ANONYMOUS(or MAP_ANON) is specified, and portable applicationsshould ensure this.  The offset argument should be zero.The use of MAP_ANONYMOUS in conjunction with MAP_SHARED issupported on Linux only since kernel 2.4.MAP_DENYWRITEThis flag is ignored.  (Long ago—Linux 2.0 and earlier—itsignaled that attempts to write to the underlying fileshould fail with ETXTBSY.  But this was a source ofdenial-of-service attacks.)MAP_EXECUTABLEThis flag is ignored.MAP_FILECompatibility flag.  Ignored.MAP_FIXEDDon't interpret addr as a hint: place the mapping atexactly that address.  addr must be suitably aligned: formost architectures a multiple of the page size issufficient; however, some architectures may imposeadditional restrictions.  If the memory region specifiedby addr and len overlaps pages of any existing mapping(s),then the overlapped part of the existing mapping(s) willbe discarded.  If the specified address cannot be used,mmap() will fail.Software that aspires to be portable should use theMAP_FIXED flag with care, keeping in mind that the exactlayout of a process's memory mappings is allowed to changesignificantly between kernel versions, C library versions,and operating system releases.  Carefully read thediscussion of this flag in NOTES!MAP_FIXED_NOREPLACE (since Linux 4.17)This flag provides behavior that is similar to MAP_FIXEDwith respect to the addr enforcement, but differs in thatMAP_FIXED_NOREPLACE never clobbers a preexisting mappedrange.  If the requested range would collide with anexisting mapping, then this call fails with the errorEEXIST.  This flag can therefore be used as a way toatomically (with respect to other threads) attempt to mapan address range: one thread will succeed; all others willreport failure.Note that older kernels which do not recognize theMAP_FIXED_NOREPLACE flag will typically (upon detecting acollision with a preexisting mapping) fall back to a "non-MAP_FIXED" type of behavior: they will return an addressthat is different from the requested address.  Therefore,backward-compatible software should check the returnedaddress against the requested address.MAP_GROWSDOWNThis flag is used for stacks.  It indicates to the kernelvirtual memory system that the mapping should extenddownward in memory.  The return address is one page lowerthan the memory area that is actually created in theprocess's virtual address space.  Touching an address inthe "guard" page below the mapping will cause the mappingto grow by a page.  This growth can be repeated until themapping grows to within a page of the high end of the nextlower mapping, at which point touching the "guard" pagewill result in a SIGSEGV signal.MAP_HUGETLB (since Linux 2.6.32)Allocate the mapping using "huge" pages.  See the Linuxkernel source fileDocumentation/admin-guide/mm/hugetlbpage.rst for furtherinformation, as well as NOTES, below.MAP_HUGE_2MB, MAP_HUGE_1GB (since Linux 3.8)Used in conjunction with MAP_HUGETLB to select alternativehugetlb page sizes (respectively, 2 MB and 1 GB) onsystems that support multiple hugetlb page sizes.More generally, the desired huge page size can beconfigured by encoding the base-2 logarithm of the desiredpage size in the six bits at the offset MAP_HUGE_SHIFT.(A value of zero in this bit field provides the defaulthuge page size; the default huge page size can bediscovered via the Hugepagesize field exposed by/proc/meminfo.)  Thus, the above two constants are definedas:#define MAP_HUGE_2MB    (21 << MAP_HUGE_SHIFT)#define MAP_HUGE_1GB    (30 << MAP_HUGE_SHIFT)The range of huge page sizes that are supported by thesystem can be discovered by listing the subdirectories in/sys/kernel/mm/hugepages.MAP_LOCKED (since Linux 2.5.37)Mark the mapped region to be locked in the same way asmlock(2).  This implementation will try to populate(prefault) the whole range but the mmap() call doesn'tfail with ENOMEM if this fails.  Therefore major faultsmight happen later on.  So the semantic is not as strongas mlock(2).  One should use mmap() plus mlock(2) whenmajor faults are not acceptable after the initializationof the mapping.  The MAP_LOCKED flag is ignored in olderkernels.MAP_NONBLOCK (since Linux 2.5.46)This flag is meaningful only in conjunction withMAP_POPULATE.  Don't perform read-ahead: create pagetables entries only for pages that are already present inRAM.  Since Linux 2.6.23, this flag causes MAP_POPULATE todo nothing.  One day, the combination of MAP_POPULATE andMAP_NONBLOCK may be reimplemented.MAP_NORESERVEDo not reserve swap space for this mapping.  When swapspace is reserved, one has the guarantee that it ispossible to modify the mapping.  When swap space is notreserved one might get SIGSEGV upon a write if no physicalmemory is available.  See also the discussion of the file/proc/sys/vm/overcommit_memory in proc(5).  In kernelsbefore 2.6, this flag had effect only for private writablemappings.MAP_POPULATE (since Linux 2.5.46)Populate (prefault) page tables for a mapping.  For a filemapping, this causes read-ahead on the file.  This willhelp to reduce blocking on page faults later.MAP_POPULATE is supported for private mappings only sinceLinux 2.6.23.MAP_STACK (since Linux 2.6.27)Allocate the mapping at an address suitable for a processor thread stack.This flag is currently a no-op on Linux.  However, byemploying this flag, applications can ensure that theytransparently obtain support if the flag is implemented inthe future.  Thus, it is used in the glibc threadingimplementation to allow for the fact that somearchitectures may (later) require special treatment forstack allocations.  A further reason to employ this flagis portability: MAP_STACK exists (and has an effect) onsome other systems (e.g., some of the BSDs).MAP_SYNC (since Linux 4.15)This flag is available only with the MAP_SHARED_VALIDATEmapping type; mappings of type MAP_SHARED will silentlyignore this flag.  This flag is supported only for filessupporting DAX (direct mapping of persistent memory).  Forother files, creating a mapping with this flag results inan EOPNOTSUPP error.Shared file mappings with this flag provide the guaranteethat while some memory is mapped writable in the addressspace of the process, it will be visible in the same fileat the same offset even after the system crashes or isrebooted.  In conjunction with the use of appropriate CPUinstructions, this provides users of such mappings with amore efficient way of making data modificationspersistent.MAP_UNINITIALIZED (since Linux 2.6.33)Don't clear anonymous pages.  This flag is intended toimprove performance on embedded devices.  This flag ishonored only if the kernel was configured with theCONFIG_MMAP_ALLOW_UNINITIALIZED option.  Because of thesecurity implications, that option is normally enabledonly on embedded devices (i.e., devices where one hascomplete control of the contents of user memory).Of the above flags, only MAP_FIXED is specified in POSIX.1-2001and POSIX.1-2008.  However, most systems also supportMAP_ANONYMOUS (or its synonym MAP_ANON).munmap()The munmap() system call deletes the mappings for the specifiedaddress range, and causes further references to addresses withinthe range to generate invalid memory references.  The region isalso automatically unmapped when the process is terminated.  Onthe other hand, closing the file descriptor does not unmap theregion.The address addr must be a multiple of the page size (but lengthneed not be).  All pages containing a part of the indicated rangeare unmapped, and subsequent references to these pages willgenerate SIGSEGV.  It is not an error if the indicated range doesnot contain any mapped pages.

RETURN VALUE

       On success, mmap() returns a pointer to the mapped area.  Onerror, the value MAP_FAILED (that is, (void *) -1) is returned,and errno is set to indicate the error.On success, munmap() returns 0.  On failure, it returns -1, anderrno is set to indicate the error (probably to EINVAL).

ERRORS

       EACCES A file descriptor refers to a non-regular file.  Or a filemapping was requested, but fd is not open for reading.  OrMAP_SHARED was requested and PROT_WRITE is set, but fd isnot open in read/write (O_RDWR) mode.  Or PROT_WRITE isset, but the file is append-only.EAGAIN The file has been locked, or too much memory has beenlocked (see setrlimit(2)).EBADF  fd is not a valid file descriptor (and MAP_ANONYMOUS wasnot set).EEXIST MAP_FIXED_NOREPLACE was specified in flags, and the rangecovered by addr and length clashes with an existingmapping.EINVAL We don't like addr, length, or offset (e.g., they are toolarge, or not aligned on a page boundary).EINVAL (since Linux 2.6.12) length was 0.EINVAL flags contained none of MAP_PRIVATE, MAP_SHARED, orMAP_SHARED_VALIDATE.ENFILE The system-wide limit on the total number of open fileshas been reached.ENODEV The underlying filesystem of the specified file does notsupport memory mapping.ENOMEM No memory is available.ENOMEM The process's maximum number of mappings would have beenexceeded.  This error can also occur for munmap(), whenunmapping a region in the middle of an existing mapping,since this results in two smaller mappings on either sideof the region being unmapped.ENOMEM (since Linux 4.7) The process's RLIMIT_DATA limit,described in getrlimit(2), would have been exceeded.EOVERFLOWOn 32-bit architecture together with the large fileextension (i.e., using 64-bit off_t): the number of pagesused for length plus number of pages used for offset wouldoverflow unsigned long (32 bits).EPERM  The prot argument asks for PROT_EXEC but the mapped areabelongs to a file on a filesystem that was mounted no-exec.EPERM  The operation was prevented by a file seal; see fcntl(2).ETXTBSYMAP_DENYWRITE was set but the object specified by fd isopen for writing.Use of a mapped region can result in these signals:SIGSEGVAttempted write into a region mapped as read-only.SIGBUS Attempted access to a page of the buffer that lies beyondthe end of the mapped file.  For an explanation of thetreatment of the bytes in the page that corresponds to theend of a mapped file that is not a multiple of the pagesize, see NOTES.

ATTRIBUTES

       For an explanation of the terms used in this section, seeattributes(7).┌──────────────────────────────────────┬───────────────┬─────────┐│Interface                             Attribute     Value   │├──────────────────────────────────────┼───────────────┼─────────┤│mmap(), munmap()                      │ Thread safety │ MT-Safe │└──────────────────────────────────────┴───────────────┴─────────┘

CONFORMING TO

       POSIX.1-2001, POSIX.1-2008, SVr4, 4.4BSD.On POSIX systems on which mmap(), msync(2), and munmap() areavailable, _POSIX_MAPPED_FILES is defined in <unistd.h> to avalue greater than 0.  (See also sysconf(3).)

NOTES

       Memory mapped by mmap() is preserved across fork(2), with thesame attributes.A file is mapped in multiples of the page size.  For a file thatis not a multiple of the page size, the remaining bytes in thepartial page at the end of the mapping are zeroed when mapped,and modifications to that region are not written out to the file.The effect of changing the size of the underlying file of amapping on the pages that correspond to added or removed regionsof the file is unspecified.On some hardware architectures (e.g., i386), PROT_WRITE impliesPROT_READ.  It is architecture dependent whether PROT_READimplies PROT_EXEC or not.  Portable programs should always setPROT_EXEC if they intend to execute code in the new mapping.The portable way to create a mapping is to specify addr as 0(NULL), and omit MAP_FIXED from flags.  In this case, the systemchooses the address for the mapping; the address is chosen so asnot to conflict with any existing mapping, and will not be 0.  Ifthe MAP_FIXED flag is specified, and addr is 0 (NULL), then themapped address will be 0 (NULL).Certain flags constants are defined only if suitable feature testmacros are defined (possibly by default): _DEFAULT_SOURCE withglibc 2.19 or later; or _BSD_SOURCE or _SVID_SOURCE in glibc 2.19and earlier.  (Employing _GNU_SOURCE also suffices, and requiringthat macro specifically would have been more logical, since theseflags are all Linux-specific.)  The relevant flags are:MAP_32BIT, MAP_ANONYMOUS (and the synonym MAP_ANON),MAP_DENYWRITE, MAP_EXECUTABLE, MAP_FILE, MAP_GROWSDOWN,MAP_HUGETLB, MAP_LOCKED, MAP_NONBLOCK, MAP_NORESERVE,MAP_POPULATE, and MAP_STACK.An application can determine which pages of a mapping arecurrently resident in the buffer/page cache using mincore(2).Using MAP_FIXED safelyThe only safe use for MAP_FIXED is where the address rangespecified by addr and length was previously reserved usinganother mapping; otherwise, the use of MAP_FIXED is hazardousbecause it forcibly removes preexisting mappings, making it easyfor a multithreaded process to corrupt its own address space.For example, suppose that thread A looks through /proc/<pid>/mapsin order to locate an unused address range that it can map usingMAP_FIXED, while thread B simultaneously acquires part or all ofthat same address range.  When thread A subsequently employsmmap(MAP_FIXED), it will effectively clobber the mapping thatthread B created.  In this scenario, thread B need not create amapping directly; simply making a library call that, internally,uses dlopen(3) to load some other shared library, will suffice.The dlopen(3) call will map the library into the process'saddress space.  Furthermore, almost any library call may beimplemented in a way that adds memory mappings to the addressspace, either with this technique, or by simply allocatingmemory.  Examples include brk(2), malloc(3), pthread_create(3),and the PAM libraries 〈http://www.linux-pam.org〉.Since Linux 4.17, a multithreaded program can use theMAP_FIXED_NOREPLACE flag to avoid the hazard described above whenattempting to create a mapping at a fixed address that has notbeen reserved by a preexisting mapping.Timestamps changes for file-backed mappingsFor file-backed mappings, the st_atime field for the mapped filemay be updated at any time between the mmap() and thecorresponding unmapping; the first reference to a mapped pagewill update the field if it has not been already.The st_ctime and st_mtime field for a file mapped with PROT_WRITEand MAP_SHARED will be updated after a write to the mappedregion, and before a subsequent msync(2) with the MS_SYNC orMS_ASYNC flag, if one occurs.Huge page (Huge TLB) mappingsFor mappings that employ huge pages, the requirements for thearguments of mmap() and munmap() differ somewhat from therequirements for mappings that use the native system page size.For mmap(), offset must be a multiple of the underlying huge pagesize.  The system automatically aligns length to be a multiple ofthe underlying huge page size.For munmap(), addr, and length must both be a multiple of theunderlying huge page size.C library/kernel differencesThis page describes the interface provided by the glibc mmap()wrapper function.  Originally, this function invoked a systemcall of the same name.  Since kernel 2.4, that system call hasbeen superseded by mmap2(2), and nowadays the glibc mmap()wrapper function invokes mmap2(2) with a suitably adjusted valuefor offset.

BUGS

       On Linux, there are no guarantees like those suggested aboveunder MAP_NORESERVE.  By default, any process can be killed atany moment when the system runs out of memory.In kernels before 2.6.7, the MAP_POPULATE flag has effect only ifprot is specified as PROT_NONE.SUSv3 specifies that mmap() should fail if length is 0.  However,in kernels before 2.6.12, mmap() succeeded in this case: nomapping was created and the call returned addr.  Since kernel2.6.12, mmap() fails with the error EINVAL for this case.POSIX specifies that the system shall always zero fill anypartial page at the end of the object and that system will neverwrite any modification of the object beyond its end.  On Linux,when you write data to such partial page after the end of theobject, the data stays in the page cache even after the file isclosed and unmapped and even though the data is never written tothe file itself, subsequent mappings may see the modifiedcontent.  In some cases, this could be fixed by calling msync(2)before the unmap takes place; however, this doesn't work ontmpfs(5) (for example, when using the POSIX shared memoryinterface documented in shm_overview(7)).

EXAMPLES

       The following program prints part of the file specified in itsfirst command-line argument to standard output.  The range ofbytes to be printed is specified via offset and length values inthe second and third command-line arguments.  The program createsa memory mapping of the required pages of the file and then useswrite(2) to output the desired bytes.Program source
       #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)intmain(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);}

SEE ALSO

       ftruncate(2), getpagesize(2), memfd_create(2), mincore(2),mlock(2), mmap2(2), mprotect(2), mremap(2), msync(2),remap_file_pages(2), setrlimit(2), shmat(2), userfaultfd(2),shm_open(3), shm_overview(7)The descriptions of the following files in proc(5):/proc/[pid]/maps, /proc/[pid]/map_files, and /proc/[pid]/smaps.B.O. Gallmeister, POSIX.4, O'Reilly, pp. 128–129 and 389–391.

COLOPHON

       This page is part of release 5.11 of the Linux man-pages project.A description of the project, information about reporting bugs,and the latest version of this page, can be found athttps://www.kernel.org/doc/man-pages/.Linux                          2021-03-22                        MMAP(2)

Pages that refer to this page: memusage(1),  alloc_hugepages(2),  arch_prctl(2),  clone(2),  execve(2),  fcntl(2),  fork(2),  futex(2),  get_mempolicy(2),  getpagesize(2),  getrlimit(2),  ioctl_userfaultfd(2),  madvise(2),  mbind(2),  memfd_create(2),  mincore(2),  mlock(2),  mmap2(2),  mprotect(2),  mremap(2),  msync(2),  open(2),  perf_event_open(2),  personality(2),  posix_fadvise(2),  prctl(2),  readahead(2),  remap_file_pages(2),  seccomp(2),  sendfile(2),  set_mempolicy(2),  shmget(2),  shmop(2),  statx(2),  syscalls(2),  uselib(2),  userfaultfd(2),  vfork(2),  avc_init(3),  avc_open(3),  cap_launch(3),  fopen(3),  mallinfo(3),  malloc(3),  malloc_stats(3),  mallopt(3),  numa(3),  pthread_attr_setguardsize(3),  pthread_attr_setstack(3),  selinux_status_open(3),  sem_init(3),  shm_open(3),  core(5),  proc(5),  systemd.exec(5),  tmpfs(5),  capabilities(7),  fanotify(7),  file-hierarchy(7),  futex(7),  inode(7),  inotify(7),  pkeys(7),  shm_overview(7),  spufs(7),  system_data_types(7),  ld.so(8),  netsniff-ng(8),  trafgen(8),  xfs_io(8)


Copyright and license for this manual page

推荐阅读


《Linux Zero-copy零拷贝技术全面揭秘》

《什么是mmap?零拷贝?DMA?》

《Linux C语言:用零拷贝技术实现TCP代理(源代码+测试服务端客户端代码)》

《Kafka和RocketMQ底层存储:零拷贝技术》

《Linux I/O原理和零拷贝Zero-copy技术全面揭秘》

《通过零拷贝进行有效的数据传输(java、c)》

《搞懂Linux零拷贝,DMA》

《【转】零拷贝的实现原理》

《CUDA零拷贝内存(zerocopy memory)》

void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset)相关推荐

  1. void *mmap(void *start,size_t length,int prot,int flags,int fd,off_t offsize);

    mmap()函数的主要用途有三个: 1.将一个普通文件映射到内存中,通常在需要对文件进行频繁读写时使用,这样用内存读写取代I/O读写,以获得较高的性能: 2.将特殊文件进行匿名内存映射,可以为关联进程 ...

  2. void指针(void*):void*存放任意对象的地址、通过(int*)a转换指针类型

    0.void*简介 void*是一种特殊的指针类型,可用于存放任意对象的地址. void *pv =&obj; // obj 可以是任意类型的对象 void指针pv只保存了对象obj的首地址, ...

  3. C语言试题二十三之编写一个函数void function(int tt[m][n],int pp[n]),tt指向一个m行n列的二维函数组,求出二维函数组每列中最小元素,并依次放入pp所指定一维数组中

    1. 题目 请编写一个函数void function(int tt[m][n],int pp[n]),tt指向一个m行n列的二维函数组,求出二维函数组每列中最小元素,并依次放入pp所指定一维数组中.二 ...

  4. int pthread_atfork(void (*prepare)(void), void (*parent)(void), void (*child)(void));

    /*** pthread_atfork 示例程序* * 作者:rtoax* 日期:2020年11月18日*/ #include <stdio.h> #include <stdlib. ...

  5. 请编写一个函数void fun(int tt[M][N],int pp[N]),tt指向一个M行N列的二维数组,求出二维数组每列中最小元素,并依次放入pp所指一维数组中。

    #include <iostream> #include<iomanip> using namespace std; #define M 3 #define N 4 /*求出二 ...

  6. C语言编程>第七周 ⑧ 请编一个函数void fun(int a[M][N],int b[N]),c指向一个M行N列的二维数组,求出二维数组每列中最大元素,并依次放入b所指一维数组中。

    例题:请编一个函数void fun(int a[M][N],int b[N]),c指向一个M行N列的二维数组,求出二维数组每列中最大元素,并依次放入b所指一维数组中.二维数组中的数己在主函数中赋予. ...

  7. error C2556: 'void __thiscall......overloaded function differs only by return type from 'int __thisc

    error C2556: 'void __thiscall......overloaded function differs only by return type from 'int __thisc ...

  8. [转]C/C++语言void及void指针深层探索

    1.概述 许多初学者对C/C++语言中的void及void指针类型不甚理解,因此在使用上出现了一些错误.本文将对void关键字的深刻含义进行解说,并详述void及void指针类型的使用方法与技巧. 2 ...

  9. C/C++语言void及void指针深层探索 .

    1.概述 许多初学者对C/C++语言中的void及void指针类型不甚理解,因此在使用上出现了一些错误.本文将对void关键字的深刻含义进行解说,并详述void及void指针类型的使用方法与技巧. 2 ...

最新文章

  1. 人工智能:从经典计算机到量子计算机,弱AI进阶到强AI时代?
  2. python使用笔记:sys.argv[]的使用
  3. C++ 统计字符串中某字符出现的次数
  4. 小县城也被互联网+撞了一下腰
  5. 【深度学习】基于深度学习的目标检测研究进展
  6. monit 内存 监控_如何借助Monit搭建服务器监控系统?(1)
  7. python怎么定义文档的行数_python删除文本中行数标签的方法
  8. “金三银四”春招指南!在线javascript
  9. 防SQL注入(转载)
  10. struts2 tag if NumberFormatException
  11. IDEA给项目添加lib/jar
  12. 西门子Step7和TIA软件“交叉引用”的使用
  13. POJ 2112 Optimal Milking(最大流)
  14. vue 扁平化_5种方式实现数组扁平化
  15. 开关电源环路学习笔记(3)-系统框图
  16. Mysql 常用 时间函数
  17. 关于AJAX的一些知识
  18. PTAJava实验六
  19. 那个网络工程师技能图谱2.0版来了,再看看你会多少
  20. LiLi-OM: 面向高性能固态激光雷达惯性里程计和建图系统

热门文章

  1. 如何做一个mysql数据库_如何创建一个简单的mysql数据库
  2. 深度优先搜索之踩方格问题
  3. 关于WS-PSNR、S-PSNR、CPP-PSNR
  4. 行内元素 块级元素之间的嵌套
  5. Active Record Query Interface 数据查询接口(界面) 看到第8节。
  6. 17.3.13--python编码问题
  7. Mac上最佳的SVN管理工具:Cornerstone
  8. 在CentOS 6安装Mysql问题
  9. (TI xDM)SSCR Module—Shared Scratch Memory
  10. 谈谈对水晶报表的看法