mmap系统调用中MAP_ANONYMOUS标志的作用是什么? [英] What is the purpose of MAP_ANONYMOUS flag in mmap system call?

查看:1027
本文介绍了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的目的是什么?任何例子都是好的.还要从哪里映射内存?

What is the purpose of using MAP_ANONYMOUS? Any example would be good. Also From where the memory will be mapped?

The use of MAP_ANONYMOUS in conjunction with MAP_SHARED is only supported on Linux since kernel 2.4.写在man页面上 如何与其他进程共享与MAP_ANONYMOUS映射的内存?

It is written on man page that The use of MAP_ANONYMOUS in conjunction with MAP_SHARED is only supported on Linux since kernel 2.4. How can i share the memory mapped with MAP_ANONYMOUS with other process?

推荐答案

匿名映射可以显示为归零虚拟文件. 匿名映射只是准备使用的大的零填充内存块. 这些映射位于堆外部,因此不会导致数据段碎片化.

Anonymous mappings can be pictured as a zeroized virtual file. Anonymous mappings are simply large, zero-filled blocks of memory ready for use. These mappings reside outside of the heap, thus do not contribute to data segment fragmentation.

MAP_ANONYMOUS + MAP_PRIVATE:

  • 每次通话都会创建一个独特的映射
  • 孩子继承了父母的映射
  • 儿童在继承映射上的文字以写时复制的方式提供
  • 使用这种映射的主要目的是分配一个新的归零内存
  • malloc使用匿名私有映射来服务大于MMAP_THRESHOLD字节的内存分配请求.
    通常,MMAP_THRESHOLD为128kB.
  • every call creates a distinct mapping
  • children inherit parent's mappings
  • childrens' writes on the inherited mapping are catered in copy-on-write manner
  • the main purpose of using this kind of mapping is to allocate a new zeroized memory
  • malloc employs anonymous private mappings to serve memory allocation requests larger than MMAP_THRESHOLD bytes.
    typically, MMAP_THRESHOLD is 128kB.

MAP_ANONYMOUS + MAP_SHARED:

  • 每次调用都会创建一个独特的映射,该映射不会与任何其他映射共享页面
  • 孩子继承了父母的映射
  • 在共享映射的其他人写在共享映射上时,没有写时复制
  • 共享的匿名映射以类似于System V内存段的方式允许IPC,但仅在相关进程之间
  • each call creates a distinct mapping that doesn't share pages with any other mapping
  • children inherit parent's mappings
  • no copy-on-write when someone else sharing the mapping writes on the shared mapping
  • shared anonymous mappings allow IPC in a manner similar to System V memory segments, but only between related processes

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

On Linux, there are two ways to create anonymous mappings:

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

  • specify MAP_ANONYMOUS flag and pass -1 for fd

    addr = mmap(NULL, length, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0); 
    if (addr == MAP_FAILED)
        exit(EXIT_FAILURE);  

  • 打开/dev/zero并传递此打开的fd

  • open /dev/zero and pass this opened fd

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

    (此方法通常在没有MAP_ANONYMOUS标志的BSD等系统上使用)

    (this method is typically used on systems like BSD, that do not have MAP_ANONYMOUS flag)

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

    Advantages of anonymous mappings:
    - no virtual address space fragmentation; after unmapping, the memory is immediately returned to the system
    - they are modifiable in terms of allocation size, permissions and they can also receive advice just like normal mappings
    - each allocation is a distinct mapping, separate from global heap

    匿名映射的缺点:
    -每个映射的大小是系统页面大小的整数倍,因此可能导致地址空间的浪费
    -与从预先分配的堆

    Disadvantages of anonymous mappings:
    - size of each mapping is an integer multiple of system's page size, thus it can lead to wastage of address space
    - creating and returning mappings incur more overhead than that of from the pre-allocated heap

    如果包含此类映射的程序派生了一个进程,则子级将继承该映射. 下面的程序演示了这种继承:

    if a program containing such mapping, forks a process, the child inherits the mapping. The following program demonstrates this kinda inheritance:

    #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

    Sources:
    The Linux Programming Interface
    Chapter 49: Memory Mappings,
    Author: Michael Kerrisk

    Linux系统编程(第3版)
    第8章:内存管理,
    作者:罗伯特·洛夫(Robert Love)

    Linux System Programming (3rd edition)
    Chapter 8: Memory Management,
    Author: Robert Love

    这篇关于mmap系统调用中MAP_ANONYMOUS标志的作用是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

  • 查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆