mmap

Inom databehandling är mmap(2) ett POSIX -kompatibelt Unix- systemanrop som mappar filer eller enheter till minnet . Det är en metod för minnesmappad fil I/O. Den implementerar efterfrågesökning eftersom filinnehållet inte omedelbart läses från disken och initialt inte använder något fysiskt RAM alls. De faktiska läsningarna från disken utförs efter att en specifik plats har nåtts, på ett lat sätt. Efter att mappningen inte längre behövs måste pekarna avmappas med munmap(2) . Skyddsinformation – till exempel att markera mappade regioner som körbara – kan hanteras med hjälp av mprotect(2) , och specialbehandling kan framtvingas med madvise(2) .

I Linux , macOS och BSD:erna kan mmap skapa flera typer av mappningar. Andra operativsystem kanske bara stöder en delmängd av dessa; till exempel kanske delade mappningar inte är praktiska i ett operativsystem utan en global VFS- eller I/O-cache.

Historia

Den ursprungliga designen av minneskartade filer kom från operativsystemet TOPS-20 . mmap och tillhörande systemanrop utformades som en del av Berkeley Software Distribution (BSD) version av Unix. Deras API beskrevs redan i 4.2BSD System Manual, även om det varken implementerades i den versionen eller i 4.3BSD. Sun Microsystems hade dock implementerat just detta API i deras SunOS- operativsystem. BSD-utvecklarna vid University of California, Berkeley bad utan framgång Sun att donera dess implementering; 4.3BSD-Reno levererades istället med en implementering baserad på det virtuella minnessystemet Mach .

Filstödd och anonym

Filstödd mappning mappar ett område av processens virtuella minne till filer; det vill säga att läsning av dessa minnesområden gör att filen läses. Det är standardmappningstypen.

Anonym mappning kartlägger ett område av processens virtuella minne som inte backas upp av någon fil. Innehållet initieras till noll. I detta avseende liknar en anonym mappning malloc , och används i vissa malloc-implementationer för vissa tilldelningar, särskilt stora. Anonyma mappningar är inte en del av POSIX-standarden, utan implementeras i nästan alla operativsystem av flaggorna MAP_ANONYMOUS och MAP_ANON .

Synlighet av minne

Om mappningen är delad ( MAP_SHARED -flaggan är inställd), så bevaras den när en process delas (med hjälp av ett fork(2) -systemanrop). Därför är skrivningar till ett kartlagt område i en process omedelbart synliga i alla relaterade (förälder, barn eller syskon) processer. Om mappningen delas och backas upp av en fil (inte MAP_ANONYMOUS ) är det garanterat att det underliggande filmediet bara skrivs efter det att det har skickats till msync(2) -systemanropet. Om mappningen däremot är privat ( MAP_PRIVATE -flaggan är inställd) kommer ändringarna varken att ses av andra processer eller skrivas till filen.

En process som läser från, eller skriver till, den underliggande filen kommer inte alltid att se samma data som en annan process som har mappat filen, eftersom segment av filen kopieras till RAM och bara periodiskt töms till disken. Synkronisering kan tvingas fram med ett anrop till msync(2) .

Att använda mmap på filer kan avsevärt minska minneskostnaderna för program som har åtkomst till samma fil; de kan dela minnesområdet som filen omfattar, istället för att ladda filen för varje program som vill ha tillgång till den. Detta innebär att mmap(2) ibland används för Interprocess Communication (IPC). På moderna operativsystem är mmap(2) vanligtvis att föredra framför System V IPC Shared Memory .

Huvudskillnaden mellan System V delat minne (shmem) och minnesmappat I/O (mmap) är att System V delat minne är beständigt: om det inte uttryckligen tas bort av en process, hålls det i minnet och förblir tillgängligt tills systemet stängs av . mmap'd-minnet är inte beständigt mellan programkörningar (såvida det inte backas upp av en fil).

Exempel på användning under programmeringsspråket C

 
 
 
 
 
 
 
 







 

            
            
            
           
          

             0  
                 

               0
               0

               
                 

         
         

           
            
         
                 
                
         0
                  
                   
                

                   
                 
                 
                
                 
        

        
         
         

           
         
         
        
         
 #inkludera  <sys/types.h>  #inkludera  <sys/mman.h>  #inkludera  <err.h>  #inkludera  <fcntl.h>  #inkludera  <stdio.h>  #inkludera  <stdlib.h>  #inkludera  <sträng .h>  #include  <unistd.h>  /* Det här exemplet visar hur en mmap av /dev/zero motsvarar att  använda anonymt minne (MAP_ANON) som inte är anslutet till någon fil.  OBS MAP_ANONYMOUS eller MAP_ANON stöds av de flesta UNIX-  versioner, vilket tar bort det ursprungliga syftet med /dev/zero.  */  /* Fungerar inte på OS X eller macOS, där du inte kan mmap över /dev/zero */  int  main  (  void  )  {  const  char  str1  []  =  "sträng 1"  ;  const  char  str2  []  =  "sträng 2"  ;  pid_t  parpid  =  getpid  (),  childpid  ;  int  fd  =  -1  ;  char  *  anon  ,  *  noll  ;  if  ((  fd  =  öppen  (  "/dev/noll"  ,  O_RDWR  ,  ))  ==  -1  )  fel  (  1  ,  "öppen"  );  anon  =  (  char  *  )  mmap  (  NULL  ,  4096  ,  PROT_READ  |  PROT_WRITE  ,  MAP_ANON  |  MAP_SHARED  ,  -1  ,  );  noll  =  (  char  *  )  mmap  (  NULL  ,  4096  ,  PROT_READ  |  PROT_WRITE  ,  MAP_SHARED  ,  fd  ,  );  if  (  anon  ==  MAP_FAILED  ||  noll  ==  MAP_FAILED  )  errx  (  1  ,  "antingen mmap"  );  strcpy  (  anon  ,  str1  );  strcpy  (  noll  ,  str1  );  printf  (  "PID %d:  \t  anonym %s, nollbackad %s  \n  "  ,  parpid  ,  anon  ,  noll  );  switch  ((  childpid  =  gaffel  ()))  {  fall  -1  :  err  (  1  ,  "gaffel"  );  /* NOTREACHED */  case  :  childpid  =  getpid  ();  printf  (  "PID %d:  \t  anonym %s, nollbackad %s  \n  "  ,  childpid  ,  anon  ,  noll  );  sömn  (  3  );  printf  (  "PID %d:  \t  anonym %s, nollbackad %s  \n  "  ,  childpid  ,  anon  ,  noll  );  munmap  (  anon  ,  4096  );  munmap  (  noll  ,  4096  );  nära  (  fd  );  returnera  EXIT_SUCCESS  ;  }  sömn  (  2  );  strcpy  (  anon  ,  str2  );  strcpy  (  noll  ,  str2  );  printf  (  "PID %d:  \t  anonym %s, nollbackad %s  \n  "  ,  parpid  ,  anon  ,  noll  );  munmap  (  anon  ,  4096  );  munmap  (  noll  ,  4096  );  nära  (  fd  );  returnera  EXIT_SUCCESS  ;  } 

exempelutdata:

PID 22475: anonym sträng 1, nollbackad sträng 1 PID 22476: anonym sträng 1, nollbackad sträng 1 PID 22475: anonym sträng 2, nollbackad sträng 2 PID 22476: anonym sträng 2, nollsträngad sträng

Se även

Vidare läsning