2015-12-02 10 views
6

Von der man SeiteWas ist der Zweck von MAP_ANONYMOUS Flag in mmap Systemaufruf?

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. 

Was ist der Zweck MAP_ANONYMOUS der Verwendung? Jedes Beispiel wäre gut. Von wo wird der Speicher abgebildet?

Es ist auf man Seite geschrieben, dass The use of MAP_ANONYMOUS in conjunction with MAP_SHARED is only supported on Linux since kernel 2.4. Wie kann ich den Speicher mit MAP_ANONYMOUS mit anderem Prozess abgebildet teilen?

Antwort

11

Anonyme Zuordnungen können als virtuelle Datei mit Nullangabe dargestellt werden. Anonyme Mappings sind einfach große, null-gefüllte Speicherblöcke, die zur Verwendung bereit sind. Diese Zuordnungen befinden sich außerhalb des Heapspeichers und tragen daher nicht zur Fragmentierung des Datensegments bei.

MAP_ANONYMOUS + MAP_PRIVATE:

  • erzeugt jeder Aufruf eine deutliche Zuordnung
  • Kinder Eltern Mappings
  • Kinder schreibt über die geerbte Mapping gesorgt in copy-on-write
  • Weise erben
  • Der Hauptzweck der Verwendung dieser Art der Zuordnung ist die Zuweisung eines neuen Null-Speicher
  • malloc beschäftigt anonymous pri vate-Zuordnungen, um Speicherzuweisungsanforderungen zu bedienen, die größer als MMAP_THRESHOLD-Bytes sind.
    In der Regel ist MMAP_THRESHOLD 128 KB.

MAP_ANONYMOUS + MAP_SHARED:

  • eah Aufruf erzeugt eine eindeutige Zuordnung, die keine Seiten mit einer anderen Abbildung
  • Kinder Zuordnungen nicht teilt
  • keine Kopie-on- des erben Eltern Schreiben Sie, wenn eine andere Person, die das Mapping teilt, auf das freigegebene Mapping schreibt
  • freigegebene anonyme Zuordnungen erlauben I PC in einer ähnlichen Weise wie System V Speichersegmente, sondern nur zwischen verwandten Prozessen

Unter Linux gibt es zwei Möglichkeiten anonyme Zuordnungen zu erstellen:

  • MAP_ANONYMOUS Flag angeben und übergeben Sie -1 für fd

    addr = mmap(NULL, length, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0); 
        if (addr == MAP_FAILED) 
         exit(EXIT_FAILURE); 
    
  • offen/dev/Null und geben diese geöffnet fd

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

    (Dieses Verfahren wird typischerweise auf Systemen wie BSD verwendet, das nicht über MAP_ANONYMOUS Flag)

Vorteile der anonymen Zuordnungen:
- keine Fragmentierung des virtuellen Adressraum; nach unmapping wird der Speicher sofort an das System
zurückgegeben - sie in Bezug auf die Zuordnungsgröße, Berechtigungen modifizierbar sind, und sie können auch Ratschläge wie normale Zuordnungen
erhalten - jede Zuordnung ist eine deutliche Abbildung, getrennt von globalen Heap

Nachteile von anonymous Mappings:
- Größe jeder Zuordnung ein ganzzahliges Vielfaches der Seitengröße des Systems, so kann es zu einer Verschwendung von Adreßraum führen
- Erstellung und zurückkehren Mappings, die mehr Overhead verursachen als die vorge von -zugewiesener Haufen

Wenn ein Programm, das ein solches Mapping enthält, einen Prozess forkiert, erbt das Kind das Mapping. Das folgende Programm veranschaulicht diese irgendwie Vererbung:

#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); 
} 

Quellen:
Die Linux Programming Interface
Kapitel 49: Speicher Mappings,
Autor: Michael Kerrisk

Linux System Programming (3rd edition)
Kapitel 8: Speicherverwaltung,
Autor: Robert Love

+1

hi @nachiketkulk, Bedeutet MAP_ANONYMOUS zusammenhängender virtueller Speicher? – ransh