RAMにロードされたプロセスによってファイルが開かれていますか?


24

たとえばsedコマンドはプログラムであり、プログラムはファイル内の体系化されたロジックであり、これらのファイルはハードディスク上のどこかにあります。ただし、コマンドの実行中は、ハードディスクからファイルのコピーがRAMに入れられ、RAMに命が吹き込まれ、処理を行うことができ、プロセスと呼ばれます

プロセスは他のファイルを利用したり、それらに読み書きしたりすることができ、それらを行う場合、それらのファイルはオープンファイルと呼ばれます。実行中のすべてのプロセスによって、開いているすべてのファイルを一覧表示するコマンドがありますlsof

OK、だから私が疑問に思うのは、コマンドの二重の寿命、1つはハードディスク上、もう1つはRAM上でも、他の種類のファイル、たとえばロジックがプログラムされていないが単にデータ。

私の想定では、プロセスによって開かれたファイルもRAMに読み込まれます。それが本当かどうかはわかりません、それは単なる直観です。

誰かがそれを理解できますか?


回答:


27

ただし、コマンドの実行中は、ハードディスクからファイルのコピーがRAMに保存され、

これは間違っています(一般的に)。プログラムが(execve(2)を介して)実行されると、プロセス(そのプログラムを実行している)は仮想アドレス空間を変更し、カーネルはその目的のためにMMUを再構成します。仮想メモリについてもお読みください。アプリケーションプログラムが使用して仮想アドレス空間を変更することができることを通知MMAP(2) &munmapMPROTECT(2)は、によっても使用される動的リンカー(参照LD-Linuxの(8) )。参照のmadvise(2) posix_fadvise(2) MLOCK(2)

将来のページフォールトはカーネルによって処理され、実行可能ファイルから(怠)に)ページがロードされます。スラッシングについてもお読みください。

カーネルは、大きなページキャッシュを維持しますcopy-on-writeについてもお読みください。readahead(2)も参照してください。

OK、だから私が疑問に思うのは、コマンドの二重の寿命、1つはハードディスク上、もう1つはRAM上でも、他の種類のファイル、たとえばロジックがプログラムされていないが単にデータ。

以下のためのシステムコールなどの読み取り(2) 書き込み(2)ページキャッシュにも使用されています。読み込むデータがそこにある場合、ディスクIOは行われません。ディスクIOが必要な場合、読み取りデータはページキャッシュに配置される可能性が非常に高くなります。したがって、実際には、同じコマンドを2回実行すると、2回目にディスクへの物理I / Oが実行されないことがあります(SSDではなく、古い回転するハードディスクがある場合は、それが聞こえる場合があります。または、ハードディスクのLEDを注意深く観察してください)。

このすべてを説明しているオペレーティングシステム:3つの簡単なピース(無料でダウンロード可能、章ごとに1つのPDFファイル)のような本を読むことをお勧めします。

参照してくださいLinuxは私のRAM食べたように、実行するコマンドをxosviewtophtopまたはcat /proc/self/mapsまたはcat /proc/$$/maps(参照PROC(5) )。

PS。私はLinuxに焦点を当てていますが、他のOSにも仮想メモリとページキャッシュがあります。


35

いいえ、ファイルを開いてもメモリに自動的に読み込まれません。それは非常に非効率です。sedたとえば、他の多くのUnixツールと同様に、入力を行ごとに読み取ります。現在の行よりも多くをメモリに保持する必要はほとんどありません。

awkそれは同じです。デフォルトでは行であるレコードを一度に読み取ります。入力データの一部を変数に格納する場合、もちろん1になります。

一部の人々は次のようなことをする習慣があります

for line in $(cat file); do ...; done

シェルは展開する必要があるため $(cat file)forループの最初の反復でさえ実行する前にコマンド置換を完全に、これ全体fileをメモリに(forループを実行するシェルが使用するメモリに)読み込みます。これは少しばかげており、また洗練されていません。代わりに、する必要があります

while IFS= read -r line; do ...; done <file

これfileにより、行ごとに処理されます(ただし、「IFS = read -r行の理解」を読んでください)。

ただし、ほとんどのユーティリティは行指向であるため、シェルでファイルを1行ずつ処理することはほとんど必要ありません(テキストを処理するためにシェルループを使用するのは悪い習慣だと思われる理由を参照してください)。

私はバイオインフォマティクスで働いており、膨大な量のゲノムデータを処理する場合、メモリに絶対に必要なデータの一部だけを保持しない限り、多くのことはできません。たとえば、VCFファイルにDNAバリアントを含む1テラバイトのデータセットから個人を特定するために使用できるデータのビットを取り除く必要がある場合(そのタイプのデータは公開できないため)、1行ずつ実行します単純なawkプログラムによる処理(VCF形式は行指向なので、これは可能です)。私ファイルをメモリに読み込んでそこで処理し、再び書き戻しません!ファイルが圧縮されている場合、zcatまたはを介してフィードしますgzip -d -c。これは、gzipデータのストリーム処理を行うため、ファイル全体をメモリに読み込むこともありません。

JSONやXMLのような行指向ではないファイル形式でも、すべてをRAMに保存せずに巨大なファイルを処理できるストリームパーサーがあります。

実行可能ファイルでは、共有ライブラリがオンデマンドでロードされたり、プロセス間で共有されたりする可能性があるため、少し複雑です(参照 たとえば、共有ライブラリのロードとRAM使用量を参照)。

キャッシングは、ここでは言及していません。これは、頻繁にアクセスされるデータを保持するためにRAMを使用するアクションです。ユーザーが多くの参照を行うことを期待して、OSにより小さなファイル(実行可能ファイルなど)がキャッシュされる場合があります。ファイルの最初の読み取りとは別に、後続のアクセスはディスクではなくRAMに対して行われます。入出力のバッファリングなどのキャッシュは、通常、ユーザーに対してほとんど透過的であり、アプリケーションなどによって割り当てられたRAMの量に応じて、キャッシュに使用されるメモリの量が動的に変化する場合があります。


1 技術的には、ほとんどのプログラムはおそらく、明示的なバッファリングを使用するか、標準I / Oライブラリが行うバッファリングを介して暗黙的に入力データのチャンクを一度に読み取り、そのチャンクをユーザーのコードに1行ずつ表示します。ディスクのブロックサイズの倍数を読み取る方が、一度に1文字を読み取るよりもはるかに効率的です。ただし、このチャンクサイズが数キロバイトを超えることはほとんどありません。


あなたは、共有ライブラリをRAMにロードすることは可能だと言いましたが、意味がなくてもRAMにデータのみを含む通常のファイルをロードすることも可能ですか?
-sharkant

1
@sharkantもちろん。すべてのファイルが保存されるまで、変数(または配列、ハッシュ、または問題の言語が提供するデータ構造)にデータを追加するだけです。アレイへの入力ファイルのすべての行を追加します。また、C関数を調べることもできますが、ここではその使用法が少し話題から外れている場合があります。awk{ a[i++] = $0 }ammap()
クサラナナンダ

6
sedawkおよびその他の行指向プログラムは、一度に1行ずつメモリに読み込まれません。プレーンテキストファイルには行インデックスが含まれておらず、ファイルシステムAPIと低レベルストレージハードウェアが1つ以上の「セクター」(通常512または1024バイト)。最初の行が処理される前に、OSによって8KB未満がメモリに読み込まれた場合、私は驚くでしょう。
ラッセルボロゴーブ

5
のようなユーティリティsedは一度に1行のみをメモリに読み込みますが、オペレーティングシステムはファイルをキャッシュするために空きRAMを使用してファイルにすばやくアクセスできることに注意してください。あなたが実行している場合はsed小さいファイルにOSがメモリにファイル全体をキャッシュし、操作がRAMに完全に行われることが可能です。参照:en.wikipedia.org/wiki/Page_cache
ショーンドーソン

5
@sharkantメモリ内で完全にアクセス可能なファイルを持つことに用途があります(他の回答を参照してください、mmapはここのキーワードシステムコールです)。たとえば、データベースシステムでは通常、アクセスを簡単かつ高速にするために、データベース全体または少なくとも一部のインデックスをメモリにマップする必要があります。これは、必ずしもすべてが実際にメモリ内にあることを意味するわけではありません。OSは、ファイルがメモリ内にあることを「ふり」することができます。これは、アプリケーションに「ここで、このメモリ範囲にファイルがある」ことを伝え、読み取りが行われると(プロセスがスワップアウトされたときのように)、データが実際に読み取られます。
ジョナスシェーファー

5

いいえ。最近はRAMのギグが素晴らしいのですが、RAMが非常に限られたリソースであり(RAMが2MBのVAX 11/750でプログラミングを学んだ)、RAMにあるのはアクティブな実行可能ファイルとデータページだけでしたアクティブなプロセス、およびバッファキャッシュにあったファイルデータ。
バッファキャッシュがフラッシュされ、データページがスワップアウトされました。そして、頻繁に。読み取り専用の実行可能ページは上書きされ、ページテーブルにマークが付けられたため、プログラムがそれらのページに再び触れた場合、ファイルシステムからページインされました。データはスワップからページインされました。上記のように、STDIOライブラリはデータをブロック単位でプルし、必要に応じてプログラムによって取得しました。fgetc、fgets、freadなど。mmapを使用すると、ファイルをプロセスのアドレス空間にマッピングできます。共有ライブラリオブジェクトまたは通常のファイル。はい、RAM内にあるかどうかにかかわらず、ある程度制御できます(mlock)が、これまでのところしかありません(mlockのエラーコードセクションを参照)。


1
「RAMはファイルに対して小さすぎる」という文は、VAXの昔のように、今では真実です。
フェデリコポロニ

1
@Federico_Poloni今日はそれほど真実ではありません。私の最後の雇用主には、1TbのRAMとわずか0.5Tbのハードディスクを備えたワークステーションクラスのPCがありました。(問題クラス:小さい入力、中程度の出力、計算中にランダムにアクセスされる大きな配列)。
nigel222
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.