Rumah >Tutorial sistem >LINUX >Pemetaan memori mmap di bawah Linux: prinsip, penggunaan dan kelebihan
Pemetaan memori mmap ialah mekanisme pengurusan memori yang penting dalam sistem Linux Ia membenarkan proses ruang pengguna untuk mengakses terus memori fizikal atau fail tanpa membuat panggilan sistem atau menyalin data. Ini boleh meningkatkan penggunaan memori dan kecekapan akses, menjimatkan sumber sistem dan masa. Tetapi, adakah anda benar-benar faham bagaimana mmap berfungsi? Adakah anda tahu cara menggunakan mmap dalam Linux? Adakah anda tahu kelebihan dan batasan mmap? Artikel ini akan memperkenalkan anda kepada pengetahuan berkaitan pemetaan memori mmap di bawah Linux secara terperinci, supaya anda boleh menggunakan dan memahami alat pengurusan memori yang berkuasa ini dengan lebih baik di bawah Linux.
2. Fungsi asas
Fungsi mmap ialah panggilan sistem di bawah unix/linux Untuk butiran, sila rujuk Bahagian 12.2 Jilid 2 "Pengaturcaraan Netword Unix".
mmap system call tidak direka bentuk sepenuhnya untuk digunakan dengan memori yang dikongsi. Ia sendiri menyediakan kaedah akses yang berbeza kepada fail biasa Proses ini boleh beroperasi pada fail biasa seperti membaca dan menulis memori. Memori kongsi IPC Posix atau Sistem V digunakan semata-mata untuk tujuan perkongsian Sudah tentu, pelaksanaan mmap() memori dikongsi juga merupakan salah satu aplikasi utamanya.
<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 digunakan untuk memetakan fail ke dalam ruang memori Secara mudah, mmap adalah untuk membuat imej kandungan fail dalam ingatan. Selepas pemetaan berjaya, pengubahsuaian pengguna pada kawasan memori ini boleh dicerminkan secara langsung dalam ruang kernel Begitu juga, pengubahsuaian ruang kernel kepada kawasan ini juga dicerminkan secara langsung dalam ruang pengguna. Kemudian ia sangat cekap untuk operasi yang memerlukan sejumlah besar penghantaran data antara ruang kernel dan ruang pengguna.
Pertama sekali, perkataan "pemetaan" mempunyai makna yang sama seperti "pemetaan satu dengan satu" yang disebut dalam kelas matematik, iaitu untuk mewujudkan surat-menyurat satu-dengan-satu Di sini, ia terutamanya merujuk kepada lokasi fail pada cakera keras dan ruang alamat logik proses Satu-dengan-satu antara kawasan yang sama saiz, seperti yang ditunjukkan dalam proses 1 dalam Rajah 1. Surat-menyurat ini adalah konsep logik semata-mata dan tidak wujud secara fizikal Sebabnya ialah ruang alamat logik proses itu sendiri tidak wujud. Dalam proses pemetaan memori, tidak ada salinan data sebenar Fail tidak dimuatkan ke dalam memori, tetapi secara logiknya dimasukkan ke dalam kod, struktur data yang berkaitan (struct address_space) ditubuhkan dan dimulakan proses Terdapat panggilan sistem mmap() untuk dilaksanakan, jadi kecekapan mewujudkan pemetaan memori adalah sangat tinggi.
Rajah 1. Prinsip pemetaan ingatan
Memandangkan pemetaan memori diwujudkan tanpa penyalinan data sebenar, bagaimanakah proses akhirnya boleh mengakses terus fail pada cakera keras melalui operasi memori? Itu bergantung pada beberapa proses yang berkaitan selepas pemetaan memori.
mmap() akan mengembalikan ptr penunjuk, yang menunjuk ke alamat dalam ruang alamat logik proses Dengan cara ini, proses tidak lagi perlu memanggil baca atau tulis untuk membaca dan menulis fail, tetapi hanya perlu menggunakan ptr untuk. mengendalikan fail. Walau bagaimanapun, ptr menunjuk ke alamat logik Untuk mengendalikan data di dalamnya, alamat logik mesti ditukar kepada alamat fizikal melalui MMU, seperti yang ditunjukkan dalam proses 2 dalam Rajah 1. Proses ini tiada kaitan dengan pemetaan memori.
Seperti yang dinyatakan sebelum ini, mewujudkan pemetaan memori sebenarnya tidak menyalin data Pada masa ini, MMU tidak dapat mencari alamat fizikal yang sepadan dengan ptr dalam jadual pemetaan alamat, iaitu, MMU gagal dan akan menghasilkan gangguan halaman. Page fault interrupt Fungsi tindak balas interrupt akan mencari halaman yang sepadan dalam swap Jika ia tidak ditemui (iaitu, fail tidak pernah dibaca ke dalam memori), fail akan dibaca dari cakera keras melalui hubungan pemetaan. ditubuhkan oleh mmap(). Masukkannya ke dalam memori fizikal, seperti yang ditunjukkan dalam proses 3 dalam Rajah 1. Proses ini tiada kaitan dengan pemetaan memori.
Jika didapati memori fizikal tidak mencukupi semasa menyalin data, halaman fizikal yang tidak digunakan buat sementara waktu akan ditukar kepada cakera keras melalui mekanisme ingatan maya (swap), seperti yang ditunjukkan dalam proses 4 dalam Rajah 1. Proses ini juga tiada kaitan dengan pemetaan memori.
从代码层面上看,从硬盘上将文件读入内存,都要经过文件系统进行数据拷贝,并且数据拷贝操作是由文件系统和硬件驱动实现的,理论上来说,拷贝数据的效率是一样的。但是通过内存映射的方法访问硬盘上的文件,效率要比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 下享受内存映射的便利和快感。
Atas ialah kandungan terperinci Pemetaan memori mmap di bawah Linux: prinsip, penggunaan dan kelebihan. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!