mmap(2) | System Calls Manual | mmap(2) |
mmap, munmap - leg-uit of ont-leg-uit bestanden of apparaten in het werkgeheugen
Standard C bibliotheek (libc, -lc)
#include <sys/mman.h>
void *mmap(void *start, size_t lengte, int prot, int vlaggen, int bi, off_t positie); int munmap(void start[.lengte], size_t lengte);
Zie NOTITIES voor informatie over functie test macro vereisten.
mmap() maakt nieuwe uit-legging aan in de virtuele adres ruimte van het aanroepende proces. Het begin adres van de nieuwe uit-legging wordt opgegeven in start. Het lengte argument specificeert de lengte van de uit-legging (die groter moet zijn dan 0).
Als start NULL is, dan kiest de kernel een (aan een pagina-uitgelijnd) adres waarop de uit-legging gemaakt moet worden; dit is de meest overdraagbare methode van het aanmaken van een nieuwe uit-legging. Als start niet NULL is, dan gebruikt de kernel het als een hint waarop de uit-legging geplaatst zou moeten worden; op Linux, zal de kernel een nabijgelegen pagina grens selecteren (maar altijd hoger of gelijk aan de waarde opgegeven in /proc/sys/vm/mmap_min_addr) en proberen om daar de uit-legging te maken. Als daar al een andere uit-legging bestaat, dan selecteert de kernel een nieuw adres dat al of niet afhankelijk is van de hint. Het adres van de nieuwe uit-legging wordt teruggegeven als resultaat van de aanroep.
De inhoud van de bestand uit-legging (in tegenstelling tot een anonieme uit-legging; zie MAP_ANONYMOUS hieronder), wordt geïnitialiseerd door lengte bytes beginnende bij de positie in het bestand (of ander object( aangewezen door de bestandsindicator bi. positie moet een meervoud zijn van de pagina grootte zoals teruggegeven door sysconf(_SC_PAGE_SIZE).
Nadat de mmap() aanroep is beëindigt kan de bestandsindicator bi onmiddellijk worden gesloten zonder het ongeldig maken van de uit-legging.
Het prot argument beschrijft de vereiste geheugen bescherming van de uit-legging (dit moet niet conflicteren met de open modus van het bestand). Het is of PROT_NONE of de bitsgewijze OR of een een of meer van de volgende vlaggen:
De vlaggen argument bepaald of updates van de uit-legging zichtbaar zijn voor andere proces uit-leggingen in dezelfde regio, en of updates worden doorgegeven naar het onderliggende bestand. Het gedrag wordt bepaald door exact een van de volgende waarden in vlaggen:
Zowel MAP_SHARED en MAP_PRIVATE worden beschreven in POSIX.1-2001 en POSIX.1-2008. MAP_SHARED_VALIDATE is een Linux uitbreiding.
In aanvulling, nul of meer van de volgende waarden kunnen worden geOF´ed in vlaggen:
#define MAP_HUGE_2MB (21 << MAP_HUGE_SHIFT) #define MAP_HUGE_1GB (30 << MAP_HUGE_SHIFT)
Van de bovenstaande vlaggen is alleen MAP_FIXED gespecificeerd in POSIX.1-2001 en POSIX.1-2008. Hoewel de meeste systemen ook MAP_ANONYMOUS ondersteunen (of zijn synoniem MAP_ANON).
De mummap() systeem aanroep verwijderd de uit-leggingen voor het aangegeven adres gebied, en zorgt er voor dat verdere referenties naar adressen in het gebied niet-geldige geheugen referenties op leveren. Het gebied wordt ook automatisch ont-uit-gelegd wanneer het proces wordt beëindigt. Aan de andere kant zal het sluiten van de bestandsindicator het gebied niet on-uitleggen.
Het adres start moet een meervoud zijn van de pagina grootte (maar lengte hoeft dat niet te zijn). Alle pagina´s die een deel van het aangegeven gebied bevatten worden ont-uit-gelegd, en volgende referenties naar deze pagina´s zullen een SIGSEGV opleveren. Het is geen fout als het aangegeven gebied enige uit-gelegde pagina´s bevat.
Bij succes geeft mmap() een pointer naar een uit-gelegd gebied terug. Bij een fout, wordt de waarde MAP_FAILED (dat is, (void *) -1) terug gegeven, en wordt errno overeenkomstig gezet.
Bij succes geeft munmap() 0 terug. Bij falen geeft het -1 terug en errno wordt overeenkomstig gezet (waarschijnlijk op EINVAL).
Het gebruik van een uit-gelegde regio kan resulteren in deze signalen:
Voor een uitleg van de termen in deze sectie, zie attributes(7).
Interface | Attribuut | Waarde |
mmap(), munmap() | Thread veiligheid | MT-Safe |
POSIX.1-2001, POSIX.1-2008, SVr4, 4.4BSD.
Op POSIX systemen waarop mmap(), msync(2), en munmap() beschikbaar zijn, is _POSIX_MAPPED_FILES gedefinieerd in <unistd.h> met een waarde groter dan 0. (Zie ook sysconf(3).)
Door mmap() in kaart gebracht geheugen wordt bewaard langs fork(2), met dezelfde attributen.
Een bestand is uit-gelegd in meervouden van de pagina grootte. Van een bestand dat geen meervoud van de pagina grootte is, worden de resterende bytes in de gedeeltelijke pagina aan het einde van de uit-legging op nul gezet tijdens het uit-leggen, en modificaties aan die regio worden niet geschreven naar het bestand. Het effect van de verandering van de grootte van het onderliggende bestand van een uit-legging op de pagina´s die overeenkomen met toegevoegde of verwijderde regio´s van dat bestand is niet gespecificeerd.
Op sommige hardware architecturen (b.v. i386), impliceert PROT_WRITE PROT_READ. Het is architectuur afhankelijk of PROT_READ al dan niet PROT_EXEC impliceert. Overdraagbare programma´s zouden altijd PROT_EXEC moeten zetten als ze van plan zijn om code uit te voeren in het nieuwe overzicht.
De overdraagbare manier om uit-leggingen te maken is door start als 0 (NULL) op te geven, en MAP_FIXED weg te laten uit vlaggen. In dat geval kiest het systeem het adres voor de uit-legging; dit adres wordt zodanig gekozen dat het niet conflicteert met enige bestaande uit-legging, en zal niet 0 zijn. Als de MAP_FIXED flag werd opgegeven, en start is 0 (NULL), dan zal het uit-gelegde adres 0 (NULL) zijn.
Bepaalde vlaggen constanten zijn alleen gedefinieerd als bepaalde feature test macro´s werden gedefinieerd (mogelijk standaard): _DEFAULT_SOURCE met glibc 2.19 of later; of _BSD_SOURCE of _SVID_SOURCE in glibc 2.19 en eerder. (Gebruik van _GNU_SOURCE is genoeg, deze macro specifiek vereisen zou meer logisch geweest zijn, omdat deze vlaggen allen Linux-specifiek zijn.) De relevante vlaggen zijn: MAP_32BIT, MAP_ANONYMOUS (en zijn synoniem MAP_ANON), MAP_DENYWRITE, MAP_EXECUTABLE, MAP_FILE, MAP_GROWSDOWN, MAP_HUGETLB, MAP_LOCKED, MAP_NONBLOCK, MAP_NORESERVE, MAP_POPULATE, en MAP_STACK.
Een applicatie kan bepalen welke pagina´s van een uit-legging aanwezig zijn in de buffer/pagina cache door mincore(2) te gebruiken.
Het enige veilige gebruik van MAP_FIXED is indien het adresbereik gespecificeerd door start en lengte voordien gereserveerd werd door een andere uit-legging; anders is het gebruik van MAP_FIXED foutgevoelig om het bestaande uit-leggingen geforceerd verwijderd, hetgeen het mogelijk maakt voor een multithreaded proces om zijn eigen adresruimte te corrumperen.
Bijvoorbeeld, neem aan dat thread A door /proc/<pid>/maps loopt om de niet gebruikte adres ruimte te vinden die het kan uit-leggen door MAP_FIXED te gebruiken, terwijl thread B tegelijkertijd een deel of alles van dezelfde adres ruimte acquireert. Wanneer nu thread A vervolgens mmap(MAP_FIXED) gebruikt dan zal deze effectief de uit-legging die thread B maakte kapot maken. In dit scenario zou thread B niet direct een uit-legging moeten maken; eenvoudig weg het aanroepen van een bibliotheek functie die, intern, dlopen(3) gebruikt, om een andere gedeelde bibliotheek te laden, is voldoende. De dlopen(3) aanroep zal de bibliotheek op de adresruimte van het proces uit-leggen. Bovendien kan bijna elke bibliotheek aanroep worden geïmplementeerd op een manier die geheugen uit-legging toevoegt aan de adres ruimte, ofwel met deze techniek, ofwel door eenvoudigweg geheugen te alloceren. Voorbeelden hiervan zijn onder anderen brk(2), malloc(3), pthread_create(3), en de PAM bibliotheken http://www.linux-pam.org.
Vanaf Linux 4.17 kan een multithreaded programma de MAP_FIXED_NOREPLACE vlaggen gebruiken om het hierboven beschreven gevaar te voorkomen bij het aanmaken van een uit-legging op een vast adres dat werd gereserveerd door een bestaande uit-legging.
Voor bestand-backed uit-leggingen, mag het st_atime veld van het uit-gelegde bestand worden geüpdatet met elk tijdstip tussen de mmap() en de daarmee overeenkomende ont-uit-legging; de eerste referentie naar een uit-gelegde pagina zal het veld updaten als het al niet geüpdatet was.
De st_ctime en st_mtime velden voor een uit-gelegd bestand met PROT_WRITE en MAP_SHARED worden geüpdatet na het schrijven naar een uit-gelegde regio, en voor een volgende msync(2) met de MS_SYNC of MS_ASYNC vlag, als er een optreed.
Voor uit-leggingen die enorme pagina´s gebruiken, verschillen de eisen voor de argumenten van mmap() en munmap() iets van de eisen voor de uit-leggingen die de eigen systeem pagina grootte gebruiken.
Voor mmap(), moet positie en lengte een meervoud van de onderliggende enorme pagina grootte zijn. Het systeem lijnt automatisch lengte op een meervoud van de onderliggende enorme pagina grootte aan.
Voor munmap(), start en lengte moeten beiden een meervoud van de onderliggende enorme pagina grootte zijn.
Deze pagina beschrijft het interface waarin glibc mmap() omwikkel functie voorziet. Origineel riep deze functie een systeem aanroep aan van dezelfde naam. Vanaf Linux 2.4 is deze systeem aanroep opgevolgd door mmap2(2), en momenteel roept de glibc mmap() omwikkel functie mmap2(2) met een geschikt aangepaste waarde voor positie.
Op Linux zijn er geen garanties zoals die, die hierboven gesuggereerd werden onder MAP_NORESERVE. Standaard kan elke proces op elke moment worden beëindigd zodra het geheugen van het systeem vol raakt.
In Linux vóór 2.6.7, heeft de MAP_POPULATE vlag alleen effect als prot werd opgegeven als PROT_NONE
SUSv3 specificeert dat mmap() moet falen als length 0 is. Echter, in kernels voor 2.6.12, was mmap() succesvol in dit geval: er werd geen uit-legging gemaakt en de aanroep retourneerde adres. Vanaf Linux 2.6.12, faalt mmap() in dit geval met de foutmelding EINVAL.
POSIX specificeert dat het systeem altijd enige gedeeltelijke pagina vult met nullen aan het einde van een object en dat het systeem nooit enige wijziging van het object zal schrijven voorbij zijn einde. Wanneer u data schrijft naar zo´n gedeeltelijke pagina na het einde van een object op Linux, dan zal deze data op de pagina cache aanwezig blijven zelfs nadat het bestand werd gesloten en ont-uit-gelegd en zelfs als de data nooit werd geschreven naar het bestand zelf, volgende uit-leggingen kunnen de gewijzigde inhoud zien. In sommige gevallen kan dit worden opgelost door het aanroepen van msync(2) voordat het ont-uit-leggen plaats vind; hoewel dit niet werkt voor tmpfs(5), (b.v. bij het gebruik van het van het POSIX gedeeld geheugen interface, zoals gedocumenteerd in shm_overview(7)).
Het volgende programma schrijft delen van het bestand, opgegeven in het eerste argument op de commando regel, naar standaard uitvoer. Het bereik van de te schrijven bytes wordt bepaald door middel van de positie en lengte waarden opgegeven in het tweede en derde argument op de commando regel. Het programma maakt een geheugen uit-legging aan van de vereiste pagina´s van het bestand en gebruikt vervolgens write(2) om de gewenste bytes te tonen.
#include <fcntl.h> #include <stdio.h> #include <stdlib.h> #include <sys/mman.h> #include <sys/stat.h> #include <unistd.h> #define handle_error(msg) \ do { perror(msg); exit(EXIT_FAILURE); } while (0) int main(int argc, char *argv[]) { int fd; char *addr; off_t offset, pa_offset; size_t length; ssize_t s; struct stat sb; 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) /* om bestand grootte te verkrijgen */ handle_error("fstat"); offset = atoi(argv[2]); pa_offset = offset & ~(sysconf(_SC_PAGE_SIZE) - 1); /* positie voor mmap() moet uitgelijnd zijn op een pagina */ if (offset >= sb.st_size) { fprintf(stderr, "positie voorbij einde van het bestand\n"); exit(EXIT_FAILURE); } if (argc == 4) { length = atoi(argv[3]); if (offset + length > sb.st_size) length = sb.st_size - offset; /* Kan geen bytes tonen voorbij einde van het bestand */ } else { /* No length arg ==> display to end of file */ length = sb.st_size - offset; } start = mmap(NULL, lengte + offset - pa_offset, PROT_READ, MAP_PRIVATE, fd, pa_offset); if (start == MAP_FAILED) handle_error("mmap"); s = write(STDOUT_FILENO, start + offset - pa_offset, lengte); if (s != lengte) { if (s == -1) handle_error("write"); fprintf(stderr, "partial write"); exit(EXIT_FAILURE); } munmap(start, lengte + offset - pa_offset); close(fd); exit(EXIT_SUCCESS); }
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)
De beschrijving van de volgende bestanden in proc(5): /proc/[pid]/maps, /proc/[pid]/map_files, en /proc/[pid]/smaps.
B.O. Gallmeister, POSIX.4, O'Reilly, pp. 128–129 en 389–391.
De Nederlandse vertaling van deze handleiding is geschreven door Jos Boersema <joshb@xs4all.nl>, Mario Blättermann <mario.blaettermann@gmail.com> en Luc Castermans <luc.castermans@gmail.com>
Deze vertaling is vrije documentatie; lees de GNU General Public License Version 3 of later over de Copyright-voorwaarden. Er is geen AANSPRAKELIJKHEID.
Indien U fouten in de vertaling van deze handleiding zou vinden, stuur een e-mail naar debian-l10n-dutch@lists.debian.org.
5 februari 2023 | Linux man-pagina's 6.03 |