プログラミング
フラットメモリ対セグメントメモリ - それは再帰的だ
Flat vs. segmented memory – it's recursive (humprog.org)
要約
この記事は、コンピュータアーキテクチャにおけるメモリ管理の進化、特にx86におけるセグメンテーションの衰退とフラットメモリモデルへの移行について論じています。Unixの影響でフラットアドレス空間が主流となりましたが、WebAssemblyやCHERIのような新しいアプローチは、安全性とセキュリティのためにメモリの細分化(非フラット化)の重要性を再認識しています。筆者は、ハードウェアが非再帰的であるのに対し、プログラマの抽象化は再帰的であるという根本的な違いを指摘し、このギャップを埋める方法としてCHERIのようなハードウェア支援のメカニズムを考察しています。
全文翻訳
コンピュータサイエンスに関する雑談、思考の脱線、貴重な時間の浪費
火曜日, 2026年8月25日
フラットメモリ対セグメントメモリ - それは再帰的だ
最近のx86セグメンテーション(1 2)への取り組みで、x86の進化における一つの傾向に気づきました。それは、64ビットへの移行や、その前の高速なシステムコール機能においても、きめ細かなメモリ保護の衰退です。これらはどちらも、286以来このアーキテクチャの特徴であった洗練されたセグメンテーションシステムを部分的に無効にしました。その説明はおそらくUnixでしょう。Unixの優位性と、フラットアドレス空間(セグメント化されたものではなく)を好む傾向は、PDP-11やPDP-7から引き継がれたものであり、「誰も」セグメンテーション機能の64ビット版を望まなかったと言えます。一方、WebAssembly愛好家の間では、「セグメントメモリが復活する」と冗談を言うことがあります。WebAssemblyは、フラットネスがそれほど絶対的ではなかったOS/2やその他の非Unix OSのプログラミングモデルへの回帰に似ています。そのような非フラットネスは、もちろん安全性とセキュリティにとって依然として非常に重要です。
私は最近、Poul-Henning Kampの常に楽しめる著作のいくつかを再読しました。彼は、フラットメモリモデルを「どんな速度でも安全ではない」と評し、それに対する反応としてCHERIを位置づけています。Kampは、フラットメモリ上でソフトウェアが行う最初のことは、それに何らかの細分化構造を課すことであると観察しています。この問いを見る一つの方法は、ハードウェアがこの細分化についてどの程度知っているべきかということです... CHERIは「はい」と言いますが、以前のハードウェアは「いいえ」と言っていました - もちろん、特定のケースでは、多くのセグメンテーション関連の機能を除いては!もちろん、x86で実現されたセグメンテーションは、きめ細かな封じ込め(すなわち、非フラットアドレス空間の適切な領域内での封じ込め)に必要なセマンティクスを持っていません。特権のないコードはセグメントレジスタをリロードでき、それによって非常に粗い4つのリング特権モデルをモジュロとして、定義された任意のセグメントに到達できます。したがって、従来のセグメントの非フラットネスは、セキュリティのためというよりは、フォルト分離のためでした。それはユーザー対システムのような粗い区別に対してのみ安全であり、それ以外では無能に対しては保護しましたが、悪意に対しては保護しませんでした。
しかし、私は「はいかいいえか」という見方は間違っていると思います。それは再帰的なのです!フラットメモリに何らかの細分化構造を課した後、私たちはそれを再度行いたいと思います。アリーナやメモリプールを考えてみてください。しかし、構造内のフィールド(さらにその中の構造)も考えてみてください。問題はフラットであるかどうかではありません - プログラマの精神的な抽象化は決してフラットではありません - しかし、根本的に再帰的な現象である細分化を、非常に非再帰的なハードウェアとどのように調和させるかということです。ハードウェアは概念的に有限状態であり、そのエンジニアリングプラクティスは固定構造と有限の深さを好む傾向があります。おそらく超CISC CPUはマイクロコードで何らかのイテレーションを提供しますが、それが限界です。ハードウェアが非再帰的でソフトウェアが再帰的な場合、それらの違いをどのように調和させることができるでしょうか?ナイーブなアプローチは、単に深さを制限することです。例えば、ハードウェアがNレベルの分解まで知っており、おそらくN=1で、残りはソフトウェアが行うとします。しかし、それは満足のいくものではありません。「プログラマが行っていることに対するハードウェアの責任放棄」です。それは非均一性を保証し、Nが高くなるにつれてハードウェアによる付加価値の喪失を保証します。
CHERIはこれをしません。ソフトウェアが再帰的なステップを処理し続けるため、再帰的な分解に対処する柔軟性を維持します。境界は任意に狭く(-ish)することができますが、ソフトウェアによって狭められ、明示的に渡されます。したがって、いつでもアクセスできるものは、ハードウェアの状態というよりは、ソフトウェアの出現によって決まります。つまり、現在実行中のコードの到達範囲内に流れ込んだもの、すなわち、到達可能な機能の推移閉包にアクセスできるメモリです。(この出現は、当然ながら、監査の明らかな困難さを開きますが、適切なツールで対処できる可能性があります。)
CHERIは皮肉なことに、ある制限によってこの柔軟性を得ています。アドレス指定は、単調に減少する境界を持つ機能導出操作の途切れないチェーンに制約されています。私はこの取引に常にいくらかの不快感を感じています。なぜなら、ソフトウェアはソフトウェアなので、一部のプログラムは、例えば奇妙な非単調なアドレス計算を実行することによって、独自の道を行くからです。何十年にもわたる、プログラマが好きなように、ある種の細分化されたアドレス空間のトラバーサルをソフトウェアで表現してきた遺産は、新しい、より意見のあるハードウェアとの摩擦を生み出しました。これを克服することは、単なる開発努力の問題ですが、その努力が正常化し、そのコストが業界全体に「成功裏に」外部化されるのは、CHERI(またはそれに類するもの)が「勝った」場合のみです。(そのコストは、もちろん、大きな利益と引き換えに来るでしょう。しかし、「勝利」は、ハードウェアの普及を達成するという意味では、ハイステークスのゲームです。)
liballocsでは、「喜んで」セキュリティへの懸念を大幅に減らし、アドレスの導出方法に関する規則を処方するビジネスに深く関わらないようにしています。代わりに、開始時点のフラットアドレス空間を再帰的に細分化する際に、実際のソフトウェアが思いついた構造を記述的に捉えることに、より多くの関心を払ってきました。その中心には再帰的な抽象化があります。割り当ては他の割り当ての中にネストされ、ツリーを形成します。また、「レベルNのカットオフ」やハードウェア/ソフトウェアの分割もありません。それは根本的にソフトウェアであり、システム内の多くの異種実装にもかかわらず、可能な限り均一な反射抽象化を使用して、構造をすべて下まで捉えたいと考えています。この「均一なインターフェース、異種実装」という考え方は、もちろんオブジェクト指向とよく関連付けられ、ハードウェアとはめったに関連付けられません。liballocs自体は、プログラムがliballocsが追跡する再帰的に細分化された構造をどのように使用するかについて意見を持っていませんが、意見を課す追加セキュリティメカニズムを構築するために間違いなく使用できます。ただし、悪意に対して安全であるかどうかは、基盤となるハードウェアが、同じアドレス空間内で、それらのメカニズム自体を保護するための有用なプリミティブを提供する場合に限られます。
残念ながら、x86スタイルのセグメンテーションは、OSが実際にそれをユーザーランドに公開していれば、ほぼ十分な基盤となっていたでしょう。「Lord of the x86 Rings」という面白いタイトルの論文は、私が望むものにほぼ近いものについて、常に思い出させられます。ちなみに、別のオブジェクト指向の話題で締めくくると、古典的な言語VMアプローチによる細分化は、ハードウェアとは完全に反対の方法で問題を回避します。すべてがほぼ最大限に細分化され、小さなオブジェクトとそれらの間の巨大な明示的な相互参照(ポインタ)関係になります。プログラマは間違いなく頭の中に粗い構造を持っていますが、それはそこに留まります。システムはそれらの周りにストレージを構造化することを申し出ません。その結果、これらのシステムは空間的局所性についても問題を抱えています。これは、バイトやワードをより大きな単位にグループ化するというハードウェアのヒューリスティックであり、それゆえ、そのようなアプローチの長年のパフォーマンス上の欠点となります。
サポート: コーヒー リカレント モア [/リサーチ] [すべてのエントリ] パーマリンク 連絡先 このページを検証