ファイルがメモリマップされているかどうかを確認するにはどうすればよいですか?


8

メモリマップファイルについて混乱しているので、いくつか質問があります。手伝っていただけるとありがたいです。

  1. ファイルシステムのディレクトリを参照し、このディレクトリにファイルがあるとします。このファイルがディスクの領域を指すのではなく、メインメモリの領域を指すことは可能ですか?
  2. これが可能であれば、これを「メモリマップファイル」と呼びますか?
  3. そのようなファイルをファイルシステム内で移動mvする(つまり、そのようなファイルをディレクトリから別のディレクトリに移動する)意味は何ですか?私が理解しているのは、ファイルがメモリマップされているため、ファイルとやり取りするプロセスは常にメインメモリの事前定義された領域に書き込み、そのファイルを(たとえばを使用してvim)開くと、メインのその領域を読み取ります。メモリ(つまり、ディスクは含まれません)。したがって、ファイルをどこに移動しても、常に正しく機能しますか?はいの場合、ファイルシステム内でファイルを移動することには意味がありますか?
  4. ファイルがメモリマップされているかどうかを確認するコマンドはありますか?
  5. 最後に、メモリマップファイルをvimで開いて変更し、保存して閉じるとvim、どうなりますか?変更は単にメインメモリに書き込まれますか?その場合、このファイルを使用する他のプロセスは、今行った変更を確認できますか?私の経験では、他のプロセスは、でファイルに変更を加えたときに、ファイルに加えた変更を認識しませんでしたvim。これの理由は何ですか?

12
これは、ファイルがハードリンクであるかどうかを確認する方法を尋ねている人を思い出させます。
Dmitry Grigoryev 2016

3
@DmitryGrigoryevそれは実際にはかなりおかしいですが、誰もが学びます:)

回答:


24

メモリマップされたファイルは、逆に機能します。メモリマッピングはファイルのプロパティではありませんが、ファイルにアクセスする方法です。プロセスは、ファイルの内容(またはそのサブセット)をアドレススペースにマップできます。これにより、ファイルの読み書きが容易になります。そのためには、単にメモリでの読み取りと書き込みが必要です。ディスク上のファイル自体は、他のファイルとまったく同じです。

これを設定するために、プロセスはmmap関数を使用します。これは、プロセス間でメモリを共有するなど、他の目的にも使用できます。


14
@Utkuこれは、メモリマップファイルとは関係ありません。
佐藤桂2016

12
MySQLサーバーをシャットダウンしなかった場合、それは通常の動作です。サーバーはファイル上でファイル記述子を開いており、それでもは有効ですmv
Stephen Kitt 2016

11
ファイル記述子は、ファイルシステム内のiノードを(最終的に)指します。これがファイルが実際に存在する場所です。ディレクトリエントリもこれらのiノードを指し、mv単にiノードではなくディレクトリエントリを変更します(同じファイルシステムでファイルを移動する場合)。
Stephen Kitt 2016

1
説明は有用な簡略化ですが、正確さのためです。メモリマッピングは、技術的にはファイル記述子と同じではありませんが、同じように機能します(ファイル名ではなくiノードを参照することにより)。open()、mmap()、close()はFDを残さず、マッピングだけを残しlsofます。これはで表示されます。プロセスがmunmap()を呼び出すか、終了するまで(またはmmap(MAP_FIXED)を使用してマッピングを別のマッピングに置き換えるまで)、終了しません
Peter Cordes

3
@Utku実際にはファイルを移動していません。同じファイルを参照する新しいディレクトリエントリを作成し、古いものを削除しました。命名の変更は、すでにファイルを開いているプロセスには影響しません。
David Schwartz

11

メモリマップトファイルは、(必ずしも)メモリによってサポートされていません。それは完全にディスク上に存在できます。実際、ファイルが存在する場所は、ファイル自体のプロパティではなく、ファイルが存在するファイルシステムのプロパティです。

メモリ内のファイルのマッピングは、メモリにファイルの一部をロードするためにプロセスが実行できる操作です。結果は、メモリの通常の領域のように見えますが、プロセスがこの領域から読み取りまたは書き込みを行うとき、実際にはファイルの読み取りと書き込みが行われる点が異なります。ファイルを開いてメモリにマップし、書き込み、保存すると、変更はファイル上、ディスク上で行われます(もちろん、ディスク上にある場合)。

あなたがアクセスの多くは、シーケンシャルになるだろうされていないファイル、上で行うことが容易と読み取りと書き込みの問題よりもメモリで行うことが、より効率的な場合があります原因であることを知っているとき、これは、例えば使用することができreadwrite、およびllseekシステムコール。この方法の唯一の問題は、ファイルを複数のプロセスで同時に読み書きする必要がある場合、実際には使用できないことです。結果は予測できません。

ファイルが現在マップされているかどうかを確認できるコマンドはありません。ただし、プロセスのマッピングを検査でき/proc/<pid>/mapsます(システムにある場合)。

2番目の質問に答えるために、ファイルを開いたときに、それをファイルシステムに移動した場合でも、ファイルを開いたプロセスは引き続きそのファイルを使用できます。何が起こるかというと、ファイルはファイルシステムのエントリに依存していません。ファイルを開いている限り、ファイルシステム内のパスが変更された場合でも、ファイルの記述子である「ハンドル」を使用して、ファイルの読み取りと書き込みを行うことができます。ファイルは、ファイルシステムにエントリがなく、ファイル記述子を保持しているプロセスがない場合にのみ消えます。


したがって、ファイルを移動しても、ファイル記述子の値は変わりません。パスからファイルへの記述子マッピングがあり、そのマッピングのパス部分のみが変更されます。これは正しいです?
Utku 2016

1
ある意味ではありますが、私はあなたを理解することができないので、言い換えさせてください。基本的に、「ファイル」は3つです。ディレクトリエントリは、ファイルシステム内のパスです。iノードはファイルの内容です。また、ファイル記述子は開いているファイルを表します。ディレクトリエントリとファイル記述子の両方に、それらのバッキングiノードへのポインタが含まれています。ファイルを開くと、ディレクトリエントリが渡され、カーネルがファイル記述子を返します。そのため、元のディレクトリエントリが変更された場合でも、ファイル記述子は同じiノードを指しているので、ファイルにアクセスできます。
lgeorget

1
ただし、でプロセスのマッピングを検査でき/proc/<pid>/mapsます。-上記のプロセス/procが最初からシステムに存在している場合。OpenBSDはサポートしておらず、FreeBSDは段階的に廃止しています。また、FreeBSDはの/proc/<pid>/map代わりに持っています/proc/<pid>/maps
佐藤桂2016

@佐藤桂精度ありがとうございます。私はLinuxマシンしか手元にないので、自分のケースについて話して、他の人に話せるようにすると思いました...ここで修正/追加する必要がある場合は、自由に回答を編集してください。
lgeorget

あなたが尋ねたので:あなたは、OPが彼が求めていることを実際に理解していると想定し、メモリマップファイルとは何かを詳細に説明しました。あなたが彼を奉仕したとは思わない。IMO上の上記の最初のコメントは、OPが実際にあなたの回答を求めていた内容とはるかに関連しています。FWIW。
佐藤桂2016

9

Q4:ファイルがメモリマップされているかどうかを通知するコマンドはありますか?

このlsofコマンドは、システムで現在使用されているすべてのファイルを表示します。ファイルがメモリマップされている場合、「FD」列には「mem」が含まれます。したがって、このコマンドの出力を、関心のあるファイル名にgrepすることができます。


3
または使用lsof -ad mem /path/to/file
ステファンChazelas

5
またはlsof -ad mem,txt /path/to/file、実行中のファイルの一部もプロセスのアドレス空間にマッピングされていますがtxtlsof出力のように見えます。
ステファンChazelas

7

あなたは、メモリマッピングがメモリ常駐ファイルシステム内のファイルと混同されているように見え、プロセスがファイルが移動されてもファイルへのアクセスを維持する方法のような他の概念と一緒です。

質問を1つずつ行って、問題を解決できるかどうか確認します。

  1. ファイルシステムのディレクトリを参照し、このディレクトリにファイルがあるとします。このファイルがディスクの領域を指すのではなく、メインメモリの領域を指すことは可能ですか?

通常、/ procにマウントされているprocfs、/ sysにあるsysfs、または/ tmpにあるtmpfsなどのメモリ常駐ファイルシステムにある場合、メインメモリを指します。

  1. これが可能であれば、これを「メモリマップファイル」と呼びますか?

いいえ。スティーブンキットが言ったように、「メモリマッピング」とは、read()や書く()。

  1. このようなファイルをファイルシステム内で移動する(つまり、そのようなファイルをディレクトリから別のディレクトリに移動する)とはどういう意味ですか?私が理解しているのは、ファイルがメモリマップされているため、ファイルと対話するプロセスは常にメインメモリの事前定義された領域に書き込み、そのファイルを開くと(たとえばvimを使用して)、その領域を読み取ります。メインメモリ(したがって、ディスクは含まれません)。したがって、ファイルをどこに移動しても、常に正しく機能しますか?はいの場合、ファイルシステム内でファイルを移動することには意味がありますか?

同じファイルシステム内で移動する場合、実際には参照、つまりiノードを1つのディレクトリから別のディレクトリに移動するだけです。このファイルが既に開かれているプログラムがある場合、ファイル記述子を介してすでにiノードが手元にあるため、同じファイルにアクセスします。これは、コメントで言及したtable_name.idbファイルで起こったことです。

  1. ファイルがメモリマップされているかどうかを確認するコマンドはありますか?

Wossnameは、メモリマップファイルに対して既にこれに回答しています。lsofどのプロセスにファイルがメモリマップされているかがわかります。

ファイルがメモリ常駐ファイルシステムにあるかどうかを知るには、dfまたは mountを使用して、ファイルシステムとそのマウントポイントを一覧表示できます。(Wikipediaなどで)ファイルシステムを検索して、メモリにどのタイプのファイルシステムが存在するかを知る必要があるだけです。

  1. 最後に、メモリマップされたファイルをvimで開いて変更を加え、vimを保存して閉じた場合、どうなりますか?変更は単にメインメモリに書き込まれますか?その場合、このファイルを使用する他のプロセスは、今行った変更を確認できますか?私の経験では、vimを使用してファイルに変更を加えたときに、他のプロセスはファイルに加えた変更を認識しませんでした。これの理由は何ですか?

個人的に、私はmmapCプログラムで関数を使用していませんが、スキミングman mmapとから理解できるように、info mmapメモリ内の表現を同期して維持することに関与する魔法はありません。基本的な形式では、mmapを呼び出すと、ファイルの内容がメモリにコピーmsyncされ、メモリからディスクに書き戻すために使用されます。ディスク上のファイルが変更された場合、それを検出してそれをマップしたすべてのプロセスのメモリ内の表現を自動的に変更する場所はありません。

編集:mmap()は実際には、特定の条件下でメモリ内の表現を同期させようとすることがわかりました。マップが読み取られるだけの場合、他のプロセスがファイルに書き込んでも、同期が維持されます。(メモリ領域に割り当てることによって)書き込まれた場合、何が起こるかは、mmap()に提供されている必須のMAP_SHAREDフラグまたはMAP_PRIVATEフラグのいずれかに依存します。MAP_PRIVATEが指定されている場合、マップはディスク上の表現から分岐し、msync()を使用するまで同期を停止します。MAP_SHAREDが提供されている場合、更新は、ファイルがマップされている他のプロセス、および(これは必ずしも即時ではありませんが)ディスク上の表現に表示されます。

既存のファイルeでvimを開き、別の端末で実行し:winotifywait -m .いるときにコマンドを実行しました。いくつかの奇妙なビットの中で、これは私が得た重要な部分inotifywaitです。

./ MOVED_FROM e
./ MOVED_TO e~
./ CREATE e
./ OPEN e
./ MODIFY e
./ CLOSE_WRITE,CLOSE e
./ ATTRIB e
./ ATTRIB e
./ DELETE e~

Vimは新しいファイルを作成し、古いファイルを削除します。ファイルを変更する代わりにこれを行う理由はこの質問の範囲を超えていますが、要点はこれが新しいファイルであり、したがって新しいiノードを持つことです。

さて、このファイルを使用する他のプロセスとはどういう意味ですか?これを行っている間にファイルを開いていたプロセスを意味する場合、変更は表示されません。これは、同じパスでファイルを開いたにもかかわらず、同じファイルではないためです。これを行った後にファイルを開く可能性のあるプロセスを意味する場合、はい、変更が表示されます。彼らはあなたが作成した新しいファイルを開くでしょう。

プログラムがユーザーインターフェイス上でファイルを開いているように見える場合がありますが、必ずしもプロセスでファイルを開いたままにすることを意味するわけではないことに注意することが重要です。上記のように、Vimはこの例です。


3
ディスク上のファイルが変更された場合、それを検出し、それをマップしたすべてのプロセスでメモリ内の表現を自動的に変更する場所はありません。」OSのページマッピングの背後にあるディスク上のファイルシステムを変更するものシステム?ブロックデバイスや、iSCSIなどで共有されているブロックデバイスへのrawアクセスを想像していますか?
David Schwartz

@ david-schwartzいいえ。2つのプロセスでファイルがopen()されていることを想像しています。プロセス1はmmap()を使用して、ファイルの内容をメモリにコピー/マップします。次に、プロセス2はwrite()(および場合によってはfsync())を使用して、ディスク上の内容を変更します。この時点で、プロセス1のメモリにあるファイルコンテンツは、プロセス2が行った変更を反映していませんよね?
JOL

いいえ、もちろん違います。このwrite関数の目的は、ファイルデータを変更することです。これは、ディスク上の内容を変更することを意味する場合とそうでない場合がありますが、それに関係するものは何でも、それを正しくするのはファイルシステムの責任です。この場合、マップされたメモリのページを変更してダーティとしてマークする必要があります。
David Schwartz

@ david-schwartz mmap()を試してみましたが、あなたの言う通りです。以前のコメントで説明したシナリオでは、プロセス1がメモリ内(マップ内)に持っていたコンテンツは、プロセス1が事前にマッピング内のメモリに書き込んでいない限り、実際に変更を反映していました。これは、変更プロセス1が行った変更がプロセス2によって行われた変更とは異なる場所にあった場合でも当てはまりました。私は、間違っている部分を取り除き、見つけたものを追加して回答を更新しました。
JoL、2016

1
@ david-schwartz申し訳ありませんが、mmapがドキュメントで指定されたものとは異なる動作をすることを意味するものではありませんでした。それはまだ範囲内にあると思いますが、「このファイルを使用する他のプロセスは今行った変更を確認できますか?」という質問は広すぎるようです。「依存する」が多すぎる。OPの必要性は純粋に独学であるように思われるため、私は正確な答えを出し、できるだけ多くの根拠をカバーしようとしましたが、私はそれをやりすぎたかもしれません。でも、かなりのことも学んだので、それでも良かったと思います。
JoL、2016
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.