Speicherzuordnung
Der Systemaufruf mmap () bietet eine Zuordnung im virtuellen Adressraum des aufrufenden Prozesses, der die Dateien oder Geräte dem Speicher zuordnet. Dies ist von zwei Arten -
File mapping or File-backed mapping- Diese Zuordnung ordnet den Bereich des virtuellen Speichers des Prozesses den Dateien zu. Dies bedeutet, dass beim Lesen oder Schreiben in diese Speicherbereiche die Datei gelesen oder geschrieben wird. Dies ist der Standardzuordnungstyp.
Anonymous mapping- Diese Zuordnung ordnet den Bereich des virtuellen Speichers des Prozesses zu, ohne von einer Datei gesichert zu werden. Der Inhalt wird auf Null initialisiert. Diese Zuordnung ähnelt der dynamischen Speicherzuweisung (malloc ()) und wird in einigen malloc () - Implementierungen für bestimmte Zuordnungen verwendet.
Der Speicher in einer Prozesszuordnung kann mit Zuordnungen in anderen Prozessen gemeinsam genutzt werden. Dies kann auf zwei Arten erfolgen:
Wenn zwei Prozesse denselben Bereich einer Datei zuordnen, teilen sie dieselben Seiten des physischen Speichers.
Wenn ein untergeordneter Prozess erstellt wird, erbt er die Zuordnungen der Eltern, und diese Zuordnungen beziehen sich auf dieselben Seiten des physischen Speichers wie die der Eltern. Bei jeder Änderung von Daten im untergeordneten Prozess werden verschiedene Seiten für den untergeordneten Prozess erstellt.
Wenn zwei oder mehr Prozesse dieselbe Seite verwenden, kann jeder Prozess die Änderungen des Seiteninhalts sehen, die von anderen Prozessen abhängig vom Zuordnungstyp vorgenommen wurden. Der Zuordnungstyp kann entweder privat oder gemeinsam genutzt werden.
Private Mapping (MAP_PRIVATE) - Änderungen am Inhalt dieser Zuordnung sind für andere Prozesse nicht sichtbar und die Zuordnung wird nicht in die zugrunde liegende Datei übertragen.
Shared Mapping (MAP_SHARED) - Änderungen am Inhalt dieser Zuordnung sind für andere Prozesse sichtbar und die Zuordnung wird in die zugrunde liegende Datei übernommen.
#include <sys/mman.h>
void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset);
Der obige Systemaufruf gibt die Startadresse des Mappings bei Erfolg oder MAP_FAILED bei Fehler zurück.
Die virtuelle Adressadresse kann entweder vom Benutzer angegeben oder vom Kernel generiert werden (wenn die Adr als NULL übergeben wird). Die angegebene Feldlänge erfordert die Größe der Zuordnung in Bytes. Das Feld prot gibt Speicherschutzwerte wie PROT_NONE, PROT_READ, PROT_WRITE, PROT_EXEC an, die für Regionen bestimmt sind, auf die möglicherweise nicht zugegriffen, gelesen, geschrieben oder ausgeführt werden darf. Dieser Wert kann einfach (PROT_NONE) oder mit einem der drei Flags (letzte 3) ORd sein. Die Feldflags geben entweder den Zuordnungstyp oder MAP_PRIVATE oder MAP_SHARED an. Das Feld 'fd' gibt den Dateideskriptor an, der die zuzuordnende Datei identifiziert, und das Feld 'offset' impliziert den Startpunkt der Datei. Wenn die gesamte Datei zugeordnet werden muss, sollte der Offset Null sein.
#include <sys/mman.h>
int munmap(void *addr, size_t length);
Der obige Systemaufruf gibt bei Erfolg 0 oder bei Fehler -1 zurück.
Der Systemaufruf munmap führt die Aufhebung der Zuordnung des bereits speicherabgebildeten Bereichs durch. Die Felder addr geben die Startadresse des Mappings an und die Länge gibt die Größe der Mappings in Bytes an, die nicht zugeordnet werden sollen. Normalerweise erfolgt die Zuordnung und Aufhebung der Zuordnung für die gesamten zugeordneten Regionen. Wenn dies anders sein muss, sollte es entweder geschrumpft oder in zwei Teile geschnitten werden. Wenn die Adresse keine Zuordnungen hat, hat dieser Aufruf keine Auswirkung und der Aufruf gibt 0 zurück (Erfolg).
Betrachten wir ein Beispiel -
Step 1 - In die Datei schreiben Alpha Numerische Zeichen wie unten gezeigt -
0 | 1 | 2 | … | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | … | 59 | 60 | 61 |
A | B | C | … | Z | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | A | b | c | … | x | y | z |
Step 2- Ordnen Sie den Dateiinhalt mit dem Systemaufruf mmap () dem Speicher zu. Dies würde die Startadresse zurückgeben, nachdem sie in den Speicher abgebildet wurde.
Step 3- Greifen Sie mit der Array-Notation auf den Dateiinhalt zu (kann auch mit der Zeigernotation zugreifen), da der teure Systemaufruf read () nicht gelesen wird. Vermeiden Sie bei der Speicherzuordnung das mehrfache Kopieren zwischen dem Benutzerbereich, den Kernelbereichspuffern und dem Puffercache.
Step 4 - Wiederholen Sie das Lesen des Dateiinhalts, bis der Benutzer "-1" eingibt (bedeutet das Ende des Zugriffs).
Step 5 - Führen Sie Bereinigungsaktivitäten durch, dh heben Sie die Zuordnung des zugeordneten Speicherbereichs (munmap ()) auf, schließen Sie die Datei und entfernen Sie die Datei.
/* Filename: mmap_test.c */
#include <stdio.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/mman.h>
void write_mmap_sample_data();
int main() {
struct stat mmapstat;
char *data;
int minbyteindex;
int maxbyteindex;
int offset;
int fd;
int unmapstatus;
write_mmap_sample_data();
if (stat("MMAP_DATA.txt", &mmapstat) == -1) {
perror("stat failure");
return 1;
}
if ((fd = open("MMAP_DATA.txt", O_RDONLY)) == -1) {
perror("open failure");
return 1;
}
data = mmap((caddr_t)0, mmapstat.st_size, PROT_READ, MAP_SHARED, fd, 0);
if (data == (caddr_t)(-1)) {
perror("mmap failure");
return 1;
}
minbyteindex = 0;
maxbyteindex = mmapstat.st_size - 1;
do {
printf("Enter -1 to quit or ");
printf("enter a number between %d and %d: ", minbyteindex, maxbyteindex);
scanf("%d",&offset);
if ( (offset >= 0) && (offset <= maxbyteindex) )
printf("Received char at %d is %c\n", offset, data[offset]);
else if (offset != -1)
printf("Received invalid index %d\n", offset);
} while (offset != -1);
unmapstatus = munmap(data, mmapstat.st_size);
if (unmapstatus == -1) {
perror("munmap failure");
return 1;
}
close(fd);
system("rm -f MMAP_DATA.txt");
return 0;
}
void write_mmap_sample_data() {
int fd;
char ch;
struct stat textfilestat;
fd = open("MMAP_DATA.txt", O_CREAT|O_TRUNC|O_WRONLY, 0666);
if (fd == -1) {
perror("File open error ");
return;
}
// Write A to Z
ch = 'A';
while (ch <= 'Z') {
write(fd, &ch, sizeof(ch));
ch++;
}
// Write 0 to 9
ch = '0';
while (ch <= '9') {
write(fd, &ch, sizeof(ch));
ch++;
}
// Write a to z
ch = 'a';
while (ch <= 'z') {
write(fd, &ch, sizeof(ch));
ch++;
}
close(fd);
return;
}
Ausgabe
Enter -1 to quit or enter a number between 0 and 61: 3
Received char at 3 is D
Enter -1 to quit or enter a number between 0 and 61: 28
Received char at 28 is 2
Enter -1 to quit or enter a number between 0 and 61: 38
Received char at 38 is c
Enter -1 to quit or enter a number between 0 and 61: 59
Received char at 59 is x
Enter -1 to quit or enter a number between 0 and 61: 65
Received invalid index 65
Enter -1 to quit or enter a number between 0 and 61: -99
Received invalid index -99
Enter -1 to quit or enter a number between 0 and 61: -1