Speicherzuordnung mmap ist ein wichtiger Speicherverwaltungsmechanismus in Linux-Systemen. Er ermöglicht Benutzern den direkten Zugriff auf physischen Speicher oder Dateien, ohne Systemaufrufe durchzuführen oder Daten zu kopieren. Dies kann die Speichernutzung und Zugriffseffizienz verbessern und so Systemressourcen und Zeit sparen. Aber verstehen Sie wirklich, wie mmap funktioniert? Wissen Sie, wie man mmap unter Linux verwendet? Kennen Sie die Vorteile und Grenzen von mmap? In diesem Artikel werden Ihnen die relevanten Kenntnisse zur Speicherzuordnung mmap unter Linux ausführlich vorgestellt, damit Sie dieses leistungsstarke Speicherverwaltungstool unter Linux besser nutzen und verstehen können.
2. Grundfunktionen
Die mmap-Funktion ist ein Systemaufruf unter Unix/Linux. Weitere Informationen finden Sie in Abschnitt 12.2 von Band 2 von „Unix Netword Programming“.
Dermmap-Systemaufruf ist nicht vollständig für die Verwendung mit gemeinsam genutztem Speicher konzipiert. Es selbst bietet eine andere Zugriffsmethode als gewöhnliche Dateien. Der Prozess kann auf gewöhnliche Dateien zugreifen, z. B. auf den Speicher lesen und schreiben. Der Shared-Memory-IPC von Posix oder System V dient ausschließlich der gemeinsamen Nutzung. Natürlich ist die mmap()-Implementierung des Shared-Memory auch eine seiner Hauptanwendungen.
<code style="display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;border-radius: 0px;font-size: 12px"> **mmap系统调用使得进程之间通过映射同一个普通文件实现共享内存。普通文件被映射到进程地址空间后,进程可以像访问普通内存一样对文件进行访问,不必再调用read(),write()等操作。mmap并不分配空间, 只是将文件映射到调用进程的地址空间里(但是会占掉你的 virutal memory), 然后你就可以用memcpy等操作写文件, 而不用write()了.写完后,内存中的内容并不会立即更新到文件中,而是有一段时间的延迟,你可以调用msync()来显式同步一下, 这样你所写的内容就能立即保存到文件里了.这点应该和驱动相关。 不过通过mmap来写文件这种方式没办法增加文件的长度, 因为要映射的长度在调用mmap()的时候就决定了.如果想取消内存映射,可以调用munmap()来取消内存映射** </code>
void * mmap(void *start, size_t length, int prot , int flags, int fd, off_t offset)
mmap wird verwendet, um Dateien im Speicher zuzuordnen. Einfach ausgedrückt dient mmap dazu, ein Bild des Inhalts einer Datei im Speicher zu erstellen. Nach erfolgreicher Zuordnung können die Änderungen des Benutzers an diesem Speicherbereich direkt im Kernelbereich widergespiegelt werden. Ebenso werden die Änderungen des Kernelbereichs an diesem Bereich auch direkt im Benutzerbereich widergespiegelt. Dann ist es sehr effizient für Vorgänge, die eine große Datenübertragung zwischen dem Kernelraum und dem Benutzerraum erfordern.
Erstens hat das Wort „Zuordnung“ die gleiche Bedeutung wie die im Mathematikunterricht erwähnte „Eins-zu-Eins-Zuordnung“, nämlich die Herstellung einer Eins-zu-Eins-Entsprechung. Hier bezieht es sich hauptsächlich auf den Standort die Datei auf der Festplatte und der logische Adressraum des Prozesses Eins-zu-eins-Korrespondenz zwischen Bereichen gleicher Größe, wie in Prozess 1 in Abbildung 1 dargestellt. Diese Entsprechung ist ein rein logisches Konzept und existiert nicht physisch. Der Grund dafür ist, dass der logische Adressraum des Prozesses selbst nicht existiert. Bei der Speicherzuordnung erfolgt keine tatsächliche Datenkopie. Die Datei wird nicht logisch in den Speicher geladen, sondern die entsprechende Datenstruktur (Struct Address_Space) wird erstellt und initialisiert Prozess Es muss ein Systemaufruf mmap() implementiert werden, sodass die Effizienz beim Einrichten der Speicherzuordnung sehr hoch ist.
Abbildung 1. Speicherzuordnungsprinzip
Wie kann der Prozess schließlich durch Speicheroperationen direkt auf die Dateien auf der Festplatte zugreifen, da die Speicherzuordnung ohne tatsächliches Kopieren der Daten erstellt wird? Das hängt von mehreren verwandten Prozessen nach der Speicherzuordnung ab.
mmap() gibt einen Zeiger ptr zurück, der auf eine Adresse im logischen Adressraum des Prozesses zeigt. Auf diese Weise muss der Prozess nicht mehr read oder write aufrufen, um die Datei zu lesen und zu schreiben, sondern muss nur ptr verwenden Betreiben Sie die Datei. Ptr zeigt jedoch auf eine logische Adresse, um die darin enthaltenen Daten zu verarbeiten. Die logische Adresse muss über die MMU in eine physische Adresse umgewandelt werden, wie in Prozess 2 in Abbildung 1 dargestellt. Dieser Vorgang hat nichts mit der Speicherzuordnung zu tun.
Wie bereits erwähnt, werden die Daten beim Einrichten der Speicherzuordnung nicht tatsächlich kopiert. Zu diesem Zeitpunkt kann die MMU die physische Adresse, die ptr entspricht, nicht in der Adresszuordnungstabelle finden. Das heißt, die MMU schlägt fehl und generiert einen Seitenfehler-Interrupt. Seitenfehler-Interrupt Die Interrupt-Antwortfunktion sucht nach der entsprechenden Seite im Swap. Wenn sie nicht gefunden werden kann (dh die Datei wurde noch nie in den Speicher eingelesen), wird die Datei über die Zuordnungsbeziehung von der Festplatte gelesen erstellt durch mmap(). Holen Sie es in den physischen Speicher, wie in Prozess 3 in Abbildung 1 gezeigt. Dieser Vorgang hat nichts mit der Speicherzuordnung zu tun.
Wenn beim Kopieren von Daten festgestellt wird, dass der physische Speicher nicht ausreicht, werden die vorübergehend nicht verwendeten physischen Seiten über den virtuellen Speichermechanismus (Swap) auf die Festplatte ausgelagert, wie in Prozess 4 in Abbildung 1 dargestellt. Dieser Vorgang hat auch nichts mit der Speicherzuordnung zu tun.
从代码层面上看,从硬盘上将文件读入内存,都要经过文件系统进行数据拷贝,并且数据拷贝操作是由文件系统和硬件驱动实现的,理论上来说,拷贝数据的效率是一样的。但是通过内存映射的方法访问硬盘上的文件,效率要比read和write系统调用高,这是为什么呢?原因是read()是系统调用,其中进行了数据拷贝,它首先将文件内容从硬盘拷贝到内核空间的一个缓冲区,如图2中过程1,然后再将这些数据拷贝到用户空间,如图2中过程2,在这个过程中,实际上完成了 两次数据拷贝 ;而mmap()也是系统调用,如前所述,mmap()中没有进行数据拷贝,真正的数据拷贝是在缺页中断处理时进行的,由于mmap()将文件直接映射到用户空间,所以中断处理函数根据这个映射关系,直接将文件从硬盘拷贝到用户空间,只进行了 一次数据拷贝 。因此,内存映射的效率要比read/write效率高。
图2.read系统调用原理
下面这个程序,通过read和mmap两种方法分别对硬盘上一个名为“mmap_test”的文件进行操作,文件中存有10000个整数,程序两次使用不同的方法将它们读出,加1,再写回硬盘。通过对比可以看出,read消耗的时间将近是mmap的两到三倍。
1 #include 2 3 #include 4 5 #include 6 7 #include 8 9 #include 10 11 #include 12 13 #include 14 15 #include 16 17 #include 18 19 20 21 #define MAX 10000 22 23 24 25 int main() 26 27 { 28 29 int i=0; 30 31 int count=0, fd=0; 32 33 struct timeval tv1, tv2; 34 35 int *array = (int *)malloc( sizeof(int)*MAX ); 36 37 38 39 /*read*/ 40 41 42 43 gettimeofday( &tv1, NULL ); 44 45 fd = open( "mmap_test", O_RDWR ); 46 47 if( sizeof(int)*MAX != read( fd, (void *)array, sizeof(int)*MAX ) ) 48 49 { 50 51 printf( "Reading data failed.../n" ); 52 53 return -1; 54 55 } 56 57 for( i=0; iif( sizeof(int)*MAX != write( fd, (void *)array, sizeof(int)*MAX ) ) 64 65 { 66 67 printf( "Writing data failed.../n" ); 68 69 return -1; 70 71 } 72 73 free( array ); 74 75 close( fd ); 76 77 gettimeofday( &tv2, NULL ); 78 79 printf( "Time of read/write: %dms/n", tv2.tv_usec-tv1.tv_usec ); 80 81 82 83 /*mmap*/ 84 85 86 87 gettimeofday( &tv1, NULL ); 88 89 fd = open( "mmap_test", O_RDWR ); 90 91 array = mmap( NULL, sizeof(int)*MAX, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0 ); 92 93 for( i=0; iprintf( "Time of mmap: %dms/n", tv2.tv_usec-tv1.tv_usec ); 110 111 112 113 return 0; 114 115 }
通过本文,你应该对 Linux 下的内存映射 mmap 有了一个深入的了解,知道了它的定义、原理、用法和优势。你也应该明白了 mmap 的适用场景和注意事项,以及如何在 Linux 下正确地使用 mmap。我们建议你在需要高效地访问物理内存或者文件时,使用 mmap 来提高程序的性能和可移植性。同时,我们也提醒你在使用 mmap 时要注意一些潜在的风险和问题,如同步、保护、错误处理等。希望本文能够帮助你更好地使用 Linux 系统,让你在 Linux 下享受内存映射的便利和快感。
Das obige ist der detaillierte Inhalt vonSpeicherzuordnung mmap unter Linux: Prinzipien, Verwendung und Vorteile. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!