メモリ マッピング mmap は Linux システムの重要なメモリ管理メカニズムであり、ユーザー空間プロセスがシステム コールやデータのコピーを経由せずに物理メモリやファイルに直接アクセスできるようにします。これにより、メモリ使用率とアクセス効率が向上し、システム リソースと時間を節約できます。しかし、mmap がどのように機能するかを本当に理解していますか? Linux で mmap を使用する方法を知っていますか? mmap の利点と制限をご存知ですか?この記事では、Linux でのこの強力なメモリ管理ツールをよりよく使用して理解できるように、Linux でのメモリ マッピング mmap の関連知識を詳しく紹介します。
2. 基本機能
mmap 関数は、unix/linux のシステムコールです。詳細については、『Unix ネットワードプログラミング』第 2 巻の 12.2 節を参照してください。
Themmap システム コールは、完全に共有メモリで使用するように設計されているわけではありません。それ自体は通常のファイルへの異なるアクセス方法を提供しており、プロセスはメモリの読み取りと書き込みのように通常のファイルを操作できます。 Posix または System V の共有メモリ IPC は純粋に共有目的に使用されますが、もちろん、共有メモリの mmap() 実装もその主要なアプリケーションの 1 つです。
リーリー リーリーMmap はファイルをメモリ空間にマップするために使用されます。簡単に言えば、mmap はメモリ内にファイルの内容のイメージを作成することです。マッピングが成功すると、このメモリ領域に対するユーザーの変更がカーネル空間に直接反映され、同様にカーネル空間によるこの領域の変更もユーザー空間に直接反映されます。これは、カーネル空間とユーザー空間の間で大量のデータ送信を必要とする操作に非常に効率的です。
######原理######実際のデータをコピーせずにメモリ マッピングが確立されるため、最終的にプロセスはメモリ操作を通じてハードディスク上のファイルにどのように直接アクセスできるのでしょうか?これは、メモリ マッピング後のいくつかの関連プロセスに依存します。
mmap() は、プロセスの論理アドレス空間内のアドレスを指すポインタ ptr を返します。この方法では、プロセスはファイルの読み取りと書き込みのために read または write を呼び出す必要がなくなり、使用するだけで済みます。ファイルを操作するにはptrを使用します。ただし、ptr は論理アドレスを指しているため、その中のデータを操作するには、図 1 の処理 2 に示すように、MMU を介して論理アドレスを物理アドレスに変換する必要があります。このプロセスはメモリ マッピングとは何の関係もありません。
前に述べたように、メモリ マッピングの確立は実際にはデータをコピーしません。この時点で、MMU はアドレス マッピング テーブルで ptr に対応する物理アドレスを見つけることができません。つまり、MMU が失敗し、ページ フォールト割り込みが発生します。ページ割り込みの割り込み応答関数は、スワップ内の対応するページを検索します。見つからない場合 (つまり、ファイルがメモリに読み込まれたことがない場合)、mmap() によって確立されたマッピング関係は、ハードディスクからページをコピーするために使用され、図 1 のプロセス 3 に示すように、ファイルは物理メモリに読み込まれます。このプロセスはメモリ マッピングとは何の関係もありません。
データのコピー時に物理メモリが不足していることが判明した場合、図 1 のプロセス 4 に示すように、一時的に未使用の物理ページが仮想メモリ機構 (スワップ) を介してハードディスクにスワップされます。このプロセスもメモリ マッピングとは何の関係もありません。
从代码层面上看,从硬盘上将文件读入内存,都要经过文件系统进行数据拷贝,并且数据拷贝操作是由文件系统和硬件驱动实现的,理论上来说,拷贝数据的效率是一样的。但是通过内存映射的方法访问硬盘上的文件,效率要比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 下享受内存映射的便利和快感。
以上がLinux でのメモリ マッピング mmap: 原理、使用法、利点の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。