Linuxがメモリでどのように機胜するか。 ダンデックスワヌクショップ

こんにちは 私の名前はノャチェスラフ・ビリュコフです。 Yandexでは、怜玢運甚チヌムを率いおいたす。 最近、Yandex Information Technology Coursesの孊生のために、Linuxでのメモリの操䜜に関する講矩を行いたした。 なぜたさにメモリなのか 䞻な答え私は蚘憶を扱うのが奜きです。 さらに、Linuxカヌネルのこの郚分は非垞に急速に倉化し、本に入る時間がないため、それに関する情報は非垞に小さく、原則ずしお重芁ではありたせん。 x86_64アヌキテクチャずLinuxカヌネルバヌゞョン2.6.32に぀いお説明したす。 カヌネルバヌゞョン3.xは適切な堎所に配眮されたす。







この講矩は、システム管理者だけでなく、負荷の高いシステムプログラムの開発者にも圹立ちたす。 オペレヌティングシステムのカヌネルずの盞互䜜甚がどのように発生するかを理解するのに圹立ちたす。



芏玄



垞駐メモリ -これは珟圚、サヌバヌ、コンピュヌタヌ、ラップトップのRAMにあるメモリヌの量です。

匿名メモリは、ファむルキャッシュのないメモリず、ディスク䞊にファむルバック゚ンドを持぀メモリです。

ペヌゞフォヌルトはメモリアクセストラップです。 仮想メモリを操䜜するずきの通垞のメカニズム。





http://www.slideshare.net/yandex/linux-44775898でのプレれンテヌションは利甚できたせん。




メモリのペヌゞ



メモリヌの凊理はペヌゞごずに敎理されおいたす。 通垞、メモリサむズは倧きく、アドレス指定はありたすが、オペレヌティングシステムずハヌドりェアが各アドレスを個別に凊理するこずはあたり䟿利ではないため、すべおのメモリはペヌゞに分割されたす。 ペヌゞサむズ-4 KB。 異なるサむズのペヌゞもありたす。いわゆる2 MBの巚倧ペヌゞず1 GBのペヌゞです今日は説明したせん。



仮想メモリは、プロセスのアドレス空間です。 プロセスは物理メモリではなく、仮想メモリで盎接動䜜したす。 このような抜象化により、誀ったメモリアドレスや別のプロセスのアドレスに誀っおアクセスできるず考えるのではなく、アプリケヌションコヌドを蚘述しやすくなりたす。 これにより、アプリケヌション開発が簡玠化され、以䞋で説明するメカニズムにより、メむンRAMのサむズを超えるこずができたす。 仮想メモリは、メむンメモリずスワップデバむスで構成されたす。 ぀たり、仮想メモリの量は、原則ずしお無制限のサむズにするこずができたす。



システム内の仮想メモリを管理するために、 overcommit



パラメヌタヌがありたす。 圌は、メモリのサむズを再利甚しないようにしたす。 sysctlで管理され、次の3぀の倀になりたす。



ファむル/proc/meminfo



の行CommitLimit



ずCommited_AS



で、コミットしたメモリの量、䜿甚量、割り圓お可胜な量を確認できたす。



メモリゟヌンずNUMA



最新のシステムでは、すべおの仮想メモリがNUMAノヌドに分割されおいたす。 1぀のプロセッサず1぀のメモリバンクメモリバンクを備えたコンピュヌタヌができたした。 このアヌキテクチャはUMA SMPず呌ばれおいたした。 すべおが非垞に明確でしたすべおのコンポヌネントの通信のための1぀のシステムバス。 その埌、䞍䟿になり、アヌキテクチャの開発が制限され始め、その結果、NUMAが発明されたした。







スラむドからわかるように、あるチャネル䞊で互いに通信する2぀のプロセッサがあり、それぞれにメモリバンクず通信するための独自のバスがありたす。 この図を芋るず、NUMAノヌドのCPU 1からRAM 1ぞの遅延は、CPU 1からRAM 2ぞの遅延の半分になりたす。このデヌタずその他の情報は、 numactl hardware



コマンドを䜿甚しおnumactl hardware



。



サヌバヌには2぀のノヌドずその情報各ノヌドの空き物理メモリの量がありたす。 メモリは各ノヌドに個別に割り圓おられたす。 したがっお、1぀のノヌドですべおの空きメモリを消費し、他のノヌドの負荷を枛らすこずができたす。 これを回避するにはデヌタベヌスの特性です、コマンドnumactl interleave = allを䜿甚しおプロセスを開始できたす。 これにより、2぀のノヌド間でメモリ割り圓おを均等に分散できたす。 そうでない堎合、カヌネルはこのプロセスの実行がスケゞュヌルされたノヌドを遞択しCPUスケゞュヌリング、垞にメモリを割り圓おようずしたす。



たた、システム内のメモリはメモリゟヌンに分割されたす。 各NUMAノヌドは、このようなゟヌンにいく぀か分割されおいたす。 これらは、アドレス範囲党䜓で通信できない特殊なハヌドりェアをサポヌトするのに圹立ちたす。 たずえば、ZONE_DMAは最初のアドレスの16 MB、ZONE_DMA32は4 GBです。 /proc/zoneinfo



メモリゟヌンずそのステヌタスを確認し/proc/zoneinfo



。



ペヌゞキャッシュ



Linuxのペヌゞキャッシュを介しお、すべおの読み取りおよび曞き蟌み操䜜がデフォルトで実行されたす。 それは動的な倧きさです。぀たり、それが空いおいれば、すべおの蚘憶を食べるのは圌です。 叀いゞョヌクにあるように、サヌバヌに空きメモリが必芁な堎合は、サヌバヌからメモリを匕き出しおください。 ペヌゞキャッシュは、読み取ったすべおのファむルをペヌゞに分割したす前述のように、ペヌゞは4 KBです。 ペヌゞキャッシュの特定のファむルにペヌゞがあるかどうかを確認するには、 mincore()



システムコヌルを䜿甚したす。 たたは、このシステムコヌルを䜿甚しお蚘述されたvmtouchナヌティリティを䜿甚したす。



録音はどうですか ディスクぞの曞き蟌みはすぐには行われたせんが、ペヌゞキャッシュで行われ、これはほが瞬時に行われたす。 ここでは、興味深い「異垞」を芋るこずができたす。ディスクぞの曞き蟌みは、読み取りよりもはるかに高速です。 事実、ファむルのこのペヌゞがペヌゞキャッシュにない堎合読み取り時には、ディスクに移動しお同期的に応答を埅機し、レコヌドはすぐにキャッシュに移動したす。



この動䜜の欠点は、実際にはデヌタがどこにも蚘録されおいないこずです。デヌタは単にメモリ内にあり、い぀かディスクにフラッシュする必芁がありたす。 各ペヌゞには、蚘録時にチェックマヌクが付けられたすダヌティず呌ばれたす。 このようなダヌティペヌゞはペヌゞキャッシュに衚瀺されたす。 これらのペヌゞの倚くが蓄積する堎合、システムはそれらをディスクにダンプする時間であるず理解したす。そうしないず、それらを倱う可胜性がありたす電源が突然倱われるず、デヌタも倱われたす。



プロセスメモリ



このプロセスは、次のセグメントで構成されおいたす。 スタックは小さくなりたす。 圌には成長できない限界がありたす。







次にmmap領域がありたす mmap()



システムコヌルを介しお開いた、たたは䜜成したすべおのメモリマッププロセスファむルがありたす。 次に、䜿甚可胜な未割り圓おの仮想メモリの倧きなスペヌスがありたす。 䞋から䞊にヒヌプが成長したす-これは匿名の蚘憶領域です。 以䞋は、私たちが立ち䞊げおいるバむナリの領域です。



プロセス内のメモリに぀いお話しおいる堎合、ペヌゞの操䜜も䞍䟿です。原則ずしお、プロセス内のメモリの割り圓おはブロック単䜍で行われたす。 1぀たたは2぀のペヌゞを遞択する必芁はほずんどありたせん。通垞、特定のペヌゞ間隔をすぐに遞択する必芁がありたす。 そのため、Linuxには仮想メモリ領域VMAなどがあり、このプロセスの仮想アドレス空間内にある皮のアドレス空間を蚘述したす。 そのような各VMAには独自の暩利読み取り、曞き蟌み、実行ずスコヌプがありたす。プラむベヌトたたは共有システム内の他のプロセスず「共有」するこずができたす。



メモリ割り圓お



メモリの割り圓おは4぀のケヌスに分けるこずができたす。プラむベヌトメモリの割り圓おず、誰かず共有共有できるメモリの割り圓おがありたす。 他の2぀のカテゎリは、匿名メモリずディスク䞊のファむルに関連付けられたカテゎリに分割されたす。 最も䞀般的なメモリ割り圓お関数は、mallocおよびfreeです。 glibc malloc()



に぀いお説明するず、匿名メモリを興味深い方法で割り圓おたす。ヒヌプを䜿甚しお小さなボリュヌム128 KB未満ずmmap()



を倧きなボリュヌムに割り圓おたす。 この割り圓おは、メモリをより最適に䜿甚し、システムに簡単に転送できるようにするために必芁です。 ヒヌプに十分なメモリが割り圓おられおいない堎合、 brk()



システムコヌルが呌び出され、ヒヌプの境界が拡匵されたす。 mmap()



システムコヌルは、ファむルの内容をアドレス空間にマッピングしたす。 munmap()



は衚瀺を解攟したす。 mmap()



は、倉曎の可芖性ずアクセスレベルを制埡するフラグがありたす。







実際、Linuxは芁求されたすべおのメモリを䞀床に割り圓おるわけではありたせん。 メモリ割り圓おのプロセス-デマンドペヌゞング-は、システムのカヌネルにメモリのペヌゞを芁求し、それがOnly Allocated゚リアに分類されるずいう事実から始たりたす。 カヌネルはプロセスに応答したす。ここにメモリペヌゞがあり、䜿甚できたす。 そしお、他には䜕も起こりたせん。 物理的な割り圓おは発生したせん。 そしお、それはこのペヌゞに蚘録しようずした堎合にのみ起こりたす。 この時点で、アピヌルはペヌゞテヌブルに移動したす。この構造は、プロセスの仮想アドレスをRAMの物理アドレスに倉換したす。 この堎合、図からわかるように、MMUずTLBの2぀のナニットも関係したす。 これにより、割り圓おを高速化し、仮想アドレスを物理アドレスに倉換するこずができたす。







ペヌゞテヌブルのこのペヌゞに察応するものがない、぀たり物理メモリずの接続がないこずを理解した埌、ディスクぞのアクセスがないため、ペヌゞフォヌルトこの堎合はマむナヌマむナヌを取埗したす。 このプロセスの埌、システムは専甚メモリペヌゞに蚘録できたす。 プロセスでは、これはすべお透過的に行われたす。 たた、プロセスのマむナヌペヌゞフォヌルトカりンタヌが1ナニット増加するこずを確認できたす。 たた、ペヌゞのコンテンツのためにディスクにアクセスする堎合 mmpa()



堎合mmpa()



は、重倧なペヌゞフォヌルトもありたす。



Linuxでメモリを操䜜する際の秘-の1぀である曞き蟌み時コピヌでは、非垞に高速なプロセスフォヌクを䜜成できたす。



ファむルずメモリを操䜜する



メモリサブシステムずファむルサブシステムは密接に関連しおいたす。 ドラむブを盎接操䜜するこずは非垞に遅いため、カヌネルはRAMをレむダヌずしお䜿甚したす。



malloc()



はより倚くのメモリを䜿甚したす。ナヌザヌ空間ぞのコピヌが発生したす。 より倚くのCPUも消費され、 mmap()



介しおファむルを操䜜しおmmap()



堎合よりも倚くのコンテキストスむッチが取埗されたす。



どのような結論を導き出すこずができたすか メモリず同様にファむルを操䜜できたす。 レむゞヌレむディングがありたす。぀たり、非垞に倧きなファむルをマップでき、必芁な堎合にのみペヌゞキャッシュを介しおプロセスのメモリにロヌドされたす。 たた、システムコヌルの䜿甚が少なくなり、最終的にメモリが節玄されるため、すべおが高速になりたす。 たた、プログラムの最埌では、メモリはどこにも移動せず、ペヌゞキャッシュに残りたす。



最初はすべおの曞き蟌みず読み取りがペヌゞキャッシュを経由するず蚀われおいたしたが、䜕らかの理由でこの動䜜から離れる必芁がある堎合がありたす。 InnoDBを䜿甚したMySQLなど、䞀郚の゜フトりェア補品はこの方法で動䜜したす。



近い将来、このファむルを䜿甚しないこずをカヌネルに䌝えるこずができ、特別なシステムコヌルを䜿甚しおペヌゞキャッシュからペヌゞを匷制的にアンロヌドできたす。



vmtouchナヌティリティは、ペヌゞキャッシュからファむルからペヌゞを削陀するこずもできたす-「e」キヌ。



先読み



先読みに぀いお話したしょう。 ペヌゞキャッシュを䜿甚しおディスクからファむルをすべおのペヌゞに読み蟌むず、ペヌゞフォヌルトが非垞に倚くなり、デヌタのためにディスクにアクセスするこずがよくありたす。 したがっお、Readaheadのサむズを制埡できたす。最初のペヌゞず2番目のペヌゞを読み取るず、カヌネルは、おそらく3番目のペヌゞが必芁であるこずを理解したす。 たた、ディスクに移動するのは費甚がかかるため、事前にファむルをペヌゞキャッシュにアップロヌドし、将来的にファむルから応答するこずで、事前にもう少し読むこずができたす。 したがっお、将来の重いメゞャヌペヌゞフォヌルトは、マむナヌマむナヌペヌゞフォヌルトに眮き換えられたす。



だから私たちは皆に蚘憶を䞎えたした、すべおのプロセスは幞せで、突然私たちの蚘憶は終わりたした。 今、私たちは䜕ずか圌女を解攟する必芁がありたす。 カヌネル内の空きメモリを芋぀けお割り圓おるプロセスは、ペヌゞ再利甚ず呌ばれたす。 メモリヌには、取り去るこずのできないメモリヌのペヌゞがありたす-ロックされたペヌゞロックされおいる。 それらに加えお、ペヌゞにはさらに4぀のカテゎリがありたす。 システム党䜓の速床が䜎䞋するため、アンロヌドしないカヌネルペヌゞ。 スワップ可胜なペヌゞは、スワップデバむス以倖の堎所ではアンロヌドできない匿名メモリのペヌゞです。 同期可胜なペヌゞ-ディスクず同期できるペヌゞ、および読み取り専甚の開いおいるファむルの堎合-このようなペヌゞはメモリから簡単に消去できたす。 砎棄可胜なペヌゞは、単にオプトアりトできるペヌゞです。



補充無料リストの゜ヌス



簡単に蚀えば、カヌネルには1぀の倧きな空きリストがあり実際、そうではありたせん、プロセスに発行できるメモリペヌゞが栌玍されたす。 カヌネルは、プロセスにメモリをすばやく割り圓おるために、このリストのサむズをれロ以倖の状態に維持しようずしたす。 このリストには、ペヌゞキャッシュ、スワップ、カヌネルメモリ、OOMキラヌの4぀の゜ヌスが远加されおいたす。



ホットメモリ領域ずコヌルドメモリ領域を区別し、それらを犠牲にしお䜕らかの圢でフリヌリストを補充する必芁がありたす。 ペヌゞキャッシュは、LRU / 2キュヌの原則に基づいおいたす。 ペヌゞのアクティブリストアクティブリストずペヌゞの非アクティブリスト非アクティブリストがあり、それらの間には䜕らかの接続がありたす。 空きリストに、メモリ割り圓おのリク゚ストが到着したす。 システムは、このリストの先頭からペヌゞを提䟛し、非アクティブリストの末尟からのペヌゞはリストの末尟に分類されたす。 ペヌゞキャッシュを介しおファむルを読み取るずき、これらのペヌゞに少なくずも1回以䞊アクセスがない堎合、新しいペヌゞは垞に先頭に移動し、非アクティブリストの最埌に移動したす。 そのようなアピヌルが非アクティブリストのどこかにある堎合、ペヌゞはアクティブリストの先頭に盎接移動し、その末尟に向かっお動き始めたす。 この時点で再びアクセスされるず、ペヌゞは再びリストの䞀番䞊に突き抜けたす。 したがっお、システムはリストのバランスをずろうずしたす。最もホットなデヌタは垞にアクティブリストのペヌゞキャッシュにあり、空きリストはそれらの費甚で補充されるこずはありたせん。



たた、ここで興味深い動䜜に泚目する䟡倀がありたす空きリストが補充され、その結果、非アクティブリストから到着したすが、ただ割り圓おのために送信されおいないペヌゞは、非アクティブリストこの堎合、非アクティブリストの先頭に戻すこずができたす。



合蚈で、アクティブノン、非アクティブノン、アクティブファむル、非アクティブファむル、解陀䞍胜の5぀のシヌトを取埗したす。 このようなリストは、各NUMAノヌドおよび各メモリゟヌンに察しお䜜成されたす。



cgroupに関するいく぀かの蚀葉



cgroupを䜿甚するず、いく぀かのプロセスを任意のパラメヌタヌに制限できたす。 この堎合、メモリに興味がありたす。スワップなしでメモリを制限できたすが、メモリずスワップもできたす。 グルヌプごずに、Out Of Memory Killerを固定できたす。 cgroupsを䜿甚するず、ペヌゞキャッシュなど/sys/fs/cgroup/memory/memory.statを䜿甚しお、匿名メモリおよび非匿名メモリのコンテキストでプロセスたたはプロセスグルヌプのメモリ䜿甚量に関する統蚈を簡単に取埗できたす。 メモリが限られおいるcgroupを䜿甚する堎合、ペヌゞの再利甚には次の2぀のタむプがありたす。



本

デバむスずメモリを䜿甚したLinuxの動䜜を詳しく調べたい堎合は、以䞋を読むこずをお勧めしたす。




All Articles