mmap系统调用中MAP_ANONYMOUS标志的用途是什么?

man页,

 MAP_ANONYMOUS The mapping is not backed by any file; its contents are initialized to zero. The fd and offset arguments are ignored; however, some implementations require fd to be -1 if MAP_ANONYMOUS (or MAP_ANON) is specified, and portable applications should ensure this. The use of MAP_ANONYMOUS in conjunction with MAP_SHARED is only supported on Linux since kernel 2.4. 

使用MAP_ANONYMOUS的目的是MAP_ANONYMOUS ? 任何例子都不错。 也从内存的映射?

它写在man页上, The use of MAP_ANONYMOUS in conjunction with MAP_SHARED is only supported on Linux since kernel 2.4. 我怎样才能与其他进程共享与MAP_ANONYMOUS映射的内存?

Solutions Collecting From Web of "mmap系统调用中MAP_ANONYMOUS标志的用途是什么?"

匿名映射可以被描绘成一个零化的虚拟文件。 匿名映射只是大量的,填满零的内存块准备使用。 这些映射驻留在堆外部,因此不会导致数据段碎片。

MAP_ANONYMOUS + MAP_PRIVATE:

  • 每个电话都会创建一个独特的映射
  • 孩子继承父母的映射
  • 儿童对继承的映射的写作是以写时复制的方式进行的
  • 使用这种映射的主要目的是分配一个新的归零内存
  • malloc使用匿名私有映射为大于MMAP_THRESHOLD字节的内存分配请求提供服务。
    通常,MMAP_THRESHOLD是128kB。

MAP_ANONYMOUS + MAP_SHARED:

  • eah调用创建一个独立的映射,不会与其他映射共享页面
  • 孩子继承父母的映射
  • 当共享映射的其他人写入共享映射时没有写入复制
  • 共享匿名映射允许IPC以类似于系统V内存段的方式,但仅在相关的进程之间

在Linux上,有两种方法来创建匿名映射:

  • 指定MAP_ANONYMOUS标志并为fd传递-1

      addr = mmap(NULL, length, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0); if (addr == MAP_FAILED) exit(EXIT_FAILURE); 
  • 打开/ dev / zero并传递这个打开的fd

      fd = open("/dev/zero", O_RDWR); addr = mmap(NULL, length, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0); 

    (这种方法通常用于像BSD这样的没有MAP_ANONYMOUS标志的系统)

匿名映射的优点:
– 没有虚拟地址空间碎片; 取消映射后,内存立即返回到系统
– 它们可以根据分配大小,权限进行修改,而且它们也可以像正常映射一样接收建议
– 每个分配都是独立的映射,与全局堆分开

匿名映射的缺点:
– 每个映射的大小是系统页面大小的整数倍,因此会导致地址空间的浪费
– 创建和返回映射会比预先分配的堆产生更多的开销

如果一个包含这样的映射的程序分叉了一个进程,那么这个孩子将继承这个映射。 下面的程序演示了这种继承:

 #ifdef USE_MAP_ANON #define _BSD_SOURCE #endif #include <stdio.h> #include <stdlib.h> #include <errno.h> #include <sys/wait.h> #include <sys/mman.h> #include <fcntl.h> #include <unistd.h> int main(int argc, char *argv[]) { /*Pointer to shared memory region*/ int *addr; #ifdef USE_MAP_ANON /*Use MAP_ANONYMOUS*/ addr = mmap(NULL, sizeof(int), PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0); if (addr == MAP_FAILED) { fprintf(stderr, "mmap() failed\n"); exit(EXIT_FAILURE); } #else /*Map /dev/zero*/ int fd; fd = open("/dev/zero", O_RDWR); if (fd == -1) { fprintf(stderr, "open() failed\n"); exit(EXIT_FAILURE); } addr = mmap(NULL, sizeof(int), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); if (addr == MAP_FAILED) { fprintf(stderr, "mmap() failed\n"); exit(EXIT_FAILURE); } if (close(fd) == -1) { /*No longer needed*/ fprintf(stderr, "close() failed\n"); exit(EXIT_FAILURE); } #endif *addr = 1; /*Initialize integer in mapped region*/ switch(fork()) { /*Parent and child share mapping*/ case -1: fprintf(stderr, "fork() failed\n"); exit(EXIT_FAILURE); case 0: /*Child: increment shared integer and exit*/ printf("Child started, value = %d\n", *addr); (*addr)++; if (munmap(addr, sizeof(int)) == -1) { fprintf(stderr, "munmap()() failed\n"); exit(EXIT_FAILURE); } exit(EXIT_SUCCESS); default: /*Parent: wait for child to terminate*/ if (wait(NULL) == -1) { fprintf(stderr, "wait() failed\n"); exit(EXIT_FAILURE); } printf("In parent, value = %d\n", *addr); if (munmap(addr, sizeof(int)) == -1) { fprintf(stderr, "munmap()() failed\n"); exit(EXIT_FAILURE); } exit(EXIT_SUCCESS); } 

资料来源:
Linux编程接口
第49章:内存映射
作者:Michael Kerrisk

Linux系统编程(第三版)
第8章:内存管理,
作者:罗伯特·爱