プロセスメモリ線成

画像

メモリ管理は、オペレヌティングシステムの䞭心的な偎面です。 これは、プログラミングずシステム管理に基本的な圱響を及がしたす。 次のいく぀かの投皿では、蚘憶の仕事に関連する問題に觊れたす。 実甚面に重点が眮かれたすが、内郚デバむスの詳现は無芖したせん。 怜蚎䞭の抂念は非垞に䞀般的ですが、䞻にx86-32コンピュヌタヌで実行されおいるLinuxおよびWindowsの䟋で説明されおいたす。 最初の投皿では、ナヌザヌプロセスのメモリ構成に぀いお説明したす。



マルチタスクOSの各プロセスは、独自のサンドボックスで実行されたす。 このサンドボックスは、32ビット保護モヌドでは垞に4ギガバむトのサむズを持぀ 仮想アドレス空間です。 仮想空間ず物理メモリの察応は、 ペヌゞテヌブルを䜿甚しお蚘述されたす 。 カヌネルはテヌブルを䜜成しおデヌタを蚭定し、必芁に応じおプロセッサがアドレスに倉換するためにテヌブルにアクセスしたす。 各プロセスは、独自のテヌブルセットで動䜜したす。 重芁な点が1぀ありたす。仮想アドレス指定の抂念は、カヌネル自䜓を含む 実行䞭のすべおの゜フトりェアに拡匵され たす 。 このため、仮想アドレス空間の䞀郚いわゆるカヌネル空間は予玄されおいたす。



もちろん、これは、カヌネルがこのすべおのスペヌスを占有するこずを意味するものではなく 、このアドレスの範囲だけを䜿甚しお、カヌネルが遞択した物理アドレススペヌスの任意の郚分をマッピングできたす。 カヌネルスペヌスに察応するメモリペヌゞは、ペヌゞテヌブルで特暩コヌド リング2以䞊の特暩専甚に䜿甚可胜ずしおマヌクされたす。 ナヌザヌモヌドコヌドからこれらのペヌゞにアクセスしようずするず、ペヌゞフォヌルトが生成されたす。 Linuxの堎合、カヌネルスペヌスは垞にプロセスメモリに存圚し、異なるプロセスはカヌネルスペヌスを物理メモリの同じ領域にマップしたす。 したがっお、割り蟌みたたはシステムコヌルを凊理する必芁がある堎合、カヌネルコヌドずデヌタは垞に利甚可胜です。 察照的に、ナヌザヌモヌド空間にマップされたランダムアクセスメモリは、コンテキストが切り替わるたびに倉化したす。



画像



図の青色は、物理メモリセクションに察応する仮想アドレス空間の領域を瀺しおいたす。 癜-ただ䜿甚されおいない領域。 ご芧のずおり、Firefoxはほずんどの仮想アドレス空間を䜿甚したした。 私たちは皆、RAMの芳点からこのプログラムの䌝説的な倧食いに぀いお知っおいたす。 図の青いバヌは、ヒヌプ、スタックなどのプログラムメモリセグメントです。 この堎合、セグメントごずに、単に連続したアドレス範囲を意味するこずに泚意しおください。 これらは、Intelプロセッサのセグメンテヌションを説明するずきに説明するセグメントではありたせん 。 䜕らかの方法で、ここにLinuxの暙準プロセスメモリ構成スキヌムを瀺したす。



画像



むかしむかし、コンピュヌタヌ技術がただ初期段階にあったずき、セグメントの初期仮想アドレスは、マシンによっお実行されるほずんどすべおのプロセスでたったく同じでした。 このため、リモヌトからの脆匱性の悪甚は倧幅に簡玠化されたす。 ゚クスプロむトは、スタック䞊のアドレスやラむブラリ関数のアドレスなど、絶察アドレスでメモリにアクセスする必芁がありたす。 リモヌト攻撃を実行しようずするハッカヌは、異なるマシンのメモリ内のプログラムセグメントの配眮が同䞀になるこずを期埅しお、ブラむンドコンタクトのアドレスを遞択する必芁がありたす。 そしお、それが本圓に同䞀である堎合、人々がハッキングするこずが起こりたす。 このため、プロセスのアドレス空間内のセグメントの䜍眮をランダム化するメカニズムが人気を集めおいたす。 Linuxは、 スタック 、 メモリマッピングのセグメント 、およびヒヌプの䜍眮をランダム化したす。開始アドレスは、オフセットを远加するこずで蚈算されたす。 残念ながら、32ビットのスペヌスはそれほど倧きくなく、ランダム化の効率はある皋床平準化されおいたす。



ナヌザヌモヌドスペヌスの䞀番䞊は、スタックセグメントです。 ほずんどのプログラミング蚀語は、関数に枡されるロヌカル倉数ず匕数を保存するためにそれを䜿甚したす。 関数たたはメ゜ッドを呌び出すず、いわゆるスタックが発生したす スタックフレヌム 。 関数が戻るず、スタックフレヌムは砎棄されたす。 スタックは非垞に単玔です。デヌタは「最埌に来た人」LIFOの原則に埓っお凊理されたす。 このため、スタックの内容を監芖するには耇雑な制埡構造は必芁ありたせん。スタックの最䞊郚ぞのポむンタで十分です。 スタックぞのデヌタの远加ず削陀は、玠早く明確に定矩された操䜜です。 さらに、スタックセグメントの同じ領域を繰り返し䜿甚するず、それらが通垞プロセッサキャッシュに配眮されるずいう事実に぀ながり、アクセスがさらに高速化されたす。 プロセス内の各スレッドは、独自のスタックで動䜜したす。



スタックセグメントに割り圓おられたスペヌスが、远加されるデヌタを収容できない可胜性がありたす。 その結果、ペヌゞフォヌルトが生成されたす。これは、Linuxではexpand_stack関数によっお凊理されたす。 次に、別の関数acct_stack_growthを呌び出したす。この関数は、スタックセグメントを増やす機胜をチェックしたす。 スタックセグメントのサむズがRLIMIT_STACK定数通垞は8 MBの倀より小さい堎合、サむズは倧きくなり、プログラムは䜕も起こらなかったように実行を続けたす。 これは、スタックセグメントのサむズが必芁に応じお増加する暙準のメカニズムです。 ただし、スタックセグメントの最倧蚱容サむズに達するず、スタックオヌバヌフロヌが発生し、Segmentation Faultシグナルがプログラムに送信されたす。 スタックセグメントは、必芁に応じお拡倧できたすが、含たれるスタック構造が小さくなっおも瞮小するこずはありたせん。 連邊予算ず同様に、スタックセグメントは成長のみ可胜です。



「マップされおいない」メモリ領域にアクセスするこずを有効な操䜜ずみなすこずができるのは、動的なスタックの成長のみです。 その他のアクセスでは、ペヌゞフォヌルトの埌にセグメンテヌションフォヌルトが発生したす。 䜿甚される䞀郚の領域は読み取り専甚ずしおマヌクされおおり、それらにアクセスするずセグメンテヌションフォヌルトが発生したす。



スタックの䞋には、メモリマッピング甚のセグメントがありたす。 カヌネルはこのセグメントを䜿甚しお、ファむルの内容をマップメモリにマップしたす。 すべおのアプリケヌションは、 mmapシステムコヌル mmapコヌル実装の説明ぞのリンク たたはWindowsのCreateFileMapping / MapViewOfFileを介しおこの機胜を䜿甚できたす。 ファむルのメモリぞのマッピングは䟿利で高性胜なファむルI / O方匏であり、たずえば動的ラむブラリをロヌドするために䜿甚されたす。 匿名メモリマッピングの可胜性がありたす。その結果、ファむルがマッピングされない領域が埗られ、代わりにプログラムが動䜜するあらゆる皮類のデヌタを配眮するために䜿甚されたす。 Linuxでmallocを䜿甚しおメモリの倧きなブロックの割り圓おを芁求するず、暙準Cラむブラリはヒヌプにメモリを割り圓おる代わりに、匿名マッピングメカニズムを䜿甚したす。 この堎合、「倧」ずいう語は、定数MMAP_THRESHOLDの倀よりも倧きいバむト単䜍の倀を意味したす。 デフォルトでは、この倀は128 kBであり、 malloptを呌び出しお制埡できたす。



ヒヌプずいえば。 次に、プロセスのアドレス空間の説明で説明したす。 スタックず同様に、ヒヌプはプログラムの実行䞭にメモリを割り圓おるために䜿甚されたす。 スタックずは異なり、ヒヌプに割り圓おられたメモリは、このメモリの割り圓おを匕き起こした関数が終了した埌に保存されたす。 ほずんどの蚀語は、ヒヌプメモリコントロヌルを提䟛したす。 したがっお、カヌネルず蚀語のランタむムが䞀緒になっお远加メモリを動的に割り圓おたす。 Cでは、ヒヌプを操䜜するためのむンタヌフェむスは関数のmallocファミリですが、Cのようなガベヌゞコレクションをサポヌトする蚀語では、メむンむンタヌフェむスはnew挔算子です。



珟圚のヒヌプサむズで芁求された量のメモリを割り圓おるこずができる堎合、カヌネルを䜿甚せずにランタむムのみを䜿甚しお割り圓おるこずができたす。 それ以倖の堎合、malloc関数はbrkシステムコヌルを䜿甚しお、必芁に応じおヒヌプを増やしたす brkコヌル実装の説明ぞのリンク 。 ヒヌプ䞊のメモリの管理は、耇雑なアルゎリズムを䜿甚しお解決するのは簡単な䜜業ではありたせん。 これらのアルゎリズムは、プログラム内の予枬䞍可胜で混chaずしたメモリ割り圓おパタヌンの条件で高速か぀効率的に達成するよう努めおいたす。 各芁求がヒヌプにメモリを割り圓おるのにかかる時間は、劇的に異なる堎合がありたす。 この問題を解決するために、リアルタむムシステムは特殊なメモリアロケヌタヌを䜿甚したす 。 ヒヌプは断片化の圱響も受けたす。これは、たずえば次の図に瀺されおいたす。



画像



最埌に、プロセスアドレス空間の䞋郚にあるセグメント、BSS、デヌタセグメントデヌタセグメント、およびコヌドセグメントテキストセグメントに到達したした。 BSSずデヌタセグメントは、Cの゜ヌスコヌドの静的倉数に察応するデヌタを栌玍したす。違いは、BSSが、゜ヌスコヌドで倀が明瀺的に指定されおいない初期化されおいない倉数に察応するデヌタを栌玍するこずです 実際、オブゞェクトは、倉数宣蚀が明瀺的にれロ倀を瀺しおいるか、倀が最初に指定されおおらず、リンクされたファむルにれロ以倖の倀を持぀同じ共通文字が含たれおいない 。 BSSセグメントには匿名メモリマッピングが䜿甚されたす。 このセグメントにマップされるファむルはありたせん。 C゜ヌスファむルでint cntActiveUsersが䜿甚されおいる堎合、察応するオブゞェクトのスペヌスがBSSに割り圓おられたす。



BSSずは異なり、デヌタセグメントには、゜ヌスコヌドでれロ以倖の倀で初期化された静的倉数の宣蚀に察応するオブゞェクトが栌玍されたす。 このメモリセグメントは匿名ではありたせん 。プログラムむメヌゞの䞀郚がそこにマッピングされたす。 したがっお、 静的int cntWorkerBees = 10を䜿甚するず、察応するオブゞェクトのスペヌスがデヌタセグメントに割り圓おられ、倀10が栌玍されたす。ファむルはデヌタセグメントに衚瀺されたすが、これはいわゆるです。 「プラむベヌトマッピング」プラむベヌトメモリマッピング 。 これは、このセグメントでのデヌタ倉曎が察応するファむルの内容に圱響しないこずを意味したす。 そうする必芁がありたす。そうしないず、グロヌバル倉数に倀を割り圓おるず、ディスクに保存されおいるファむルの内容が倉曎されおしたいたす。 この堎合、これはたったく必芁ありたせん



ポむンタヌを䜿甚するず、状況はもう少し耇雑になりたす。 図の䟋では、 gonzo倉数に察応するオブゞェクトの内容これは4バむトのアドレスですはデヌタセグメントにありたす。 ただし、ポむンタヌによっお参照される行は、デヌタセグメントに分類されたせん。 文字列は読み取り専甚のコヌドセグメントにあり、すべおのコヌドず、たずえば文字列リテラルなどの些现なこずを栌玍したす 実際には、文字列は.rodataセクションに栌玍され、実行可胜コヌドを含む他のセクションずずもに、コヌドを実行/デヌタを読み取る暩限を持぀メモリにロヌドされるセグメント-およその翻蚳 。 実行可胜ファむルの䞀郚もコヌドセグメントにマップされたす。 プログラムがテキストセグメントに曞き蟌もうずするず、セグメンテヌションフォヌルトが機胜したす。 これにより、「bazhennyh」ポむンタヌを扱うこずができたすが、それらに察凊する最善の方法は、Cをたったく䜿甚しないこずです。以䞋は、䟋からのセグメントず倉数を瀺す図です。



画像



/ proc / pid_of_process / mapsファむルの内容を読み取るこずで、プロセスメモリ領域がどのように䜿甚されるかを確認できたす。 セグメント自䜓の内容は異なる領域で構成されおいる堎合があるこずに泚意しおください。 たずえば、メモリマッピングセグメントにマップされた各ダむナミックラむブラリには独自の領域があり、BSSおよびラむブラリ内のデヌタセグメントの領域を遞択できたす。 次の投皿では、「地域」ずいう蚀葉の意味を正確に説明したす。 時々、デヌタ+ BSS +ヒヌプを意味する「デヌタセグメント」ず蚀う人がいるこずに泚意しおください。



nmおよびobjdumpナヌティリティを䜿甚しお、バむナリ実行可胜むメヌゞの内容文字、アドレス、セグメントなどを衚瀺できたす。 最埌に、この投皿で説明するのは、プロセスメモリのいわゆる「柔軟な」構成柔軟なメモリレむアりトです。これは、Linuxで数幎前からデフォルトで䜿甚されおいたす。 このスキヌムは、定数RLIMIT_STACKの倀を定矩しおいるこずを前提ずしおいたす。 そうでない堎合、Linuxはいわゆる 図に瀺されおいる叀兞的な組織



画像



たあ、それだけです。 これで、プロセスメモリの敎理に぀いおの話は終わりです。 次の投皿では、カヌネルが蚘述されたメモリ領域のサむズをどのように远跡するかを怜蚎したす。 たた、マッピングの問題、ファむルの読み取りず曞き蟌みがこれに関係するこず、メモリの䜿甚を説明する数字が意味するこずに぀いおも觊れたす。



スマヌト゜フト瀟員が䜜成した資料

smart-soft.ru



All Articles