ホームページ >システムチュートリアル >Linux >Linux カーネルプルーニングフレームワークに関する予備調査
オペレーティング システム カーネルの不安定性、適時性の低さ、整合性の問題、および手動介入の必要性のため、Linux カーネル プルーニング テクノロジは広く使用されていません。既存のテクノロジーの限界を理解した後、これらの問題を解決できる可能性のある Linux カーネル調整フレームワークの提案を試みます。
2000 年頃、このプログラマーはまだ若く、携帯電話のオペレーティング システムとして Linux を使用したいと考えていたため、カーネル テーラリングのアイデアを思いつき、その実践を支援しました。効果は非常に良好で、すでに PDA 上で実行できました。携帯電話の機能はなくなりました。 20年以上が経過し、Linuxは大きく変化し、カーネルプルーニングの技術や手法も大きく異なりました。
Linux カーネル プルーニングは、ターゲット アプリケーション内の不要なカーネル コードを削減することです。これにより、セキュリティとパフォーマンスの点で大きな利点が得られます (起動時間の短縮とメモリ フットプリントの削減)。しかし、既存のカーネル プルーニング テクノロジーには限界があります。カーネル プルーニングのためのフレームワーク手法はあるのでしょうか?
1. カーネルクリッピングについて
近年、Linux オペレーティング システムは複雑さと規模が増大しています。ただし、アプリケーションは通常、OS 機能の一部のみを必要とし、多数のアプリケーション要件が Linux カーネルの肥大化につながります。オペレーティング システムのカーネルの肥大化は、セキュリティ リスク、起動時間の延長、メモリ使用量の増加にもつながります。
サービス化とマイクロサービスの人気により、カーネルの調整の必要性がさらに高まっています。これらのシナリオでは、仮想マシンは小規模なアプリケーションを実行します。各アプリケーションは多くの場合「マイクロ」であり、カーネル フットプリントが小さいです。一部の仮想化テクノロジは、ターゲット アプリケーションに最も単純な Linux カーネルを提供します。
オペレーティング システムの複雑さを考慮すると、カーネル機能を手動で選択してカーネルを調整することは、ある程度現実的ではありません。たとえば、Linux には 14,000 を超える構成オプション (v4.14 時点) があり、毎年数百の新しいオプションが導入されています。カーネル コンフィギュレータ (KConfig など) は、構成オプションを選択するためのユーザー インターフェイスのみを提供します。使いやすさが悪く、ドキュメントが不完全であるため、ユーザーが最小限で実用的なカーネル構成を選択するのは困難です。
既存のカーネル プルーニング テクノロジは通常、次の 3 つのステップに従います。
ただし、カーネル プルーニング手法はセキュリティとパフォーマンスの点で非常に魅力的ですが、実際には広く採用されていません。これは需要がないためではありません。実際、多くのクラウド プロバイダーはコードを減らすために Linux カーネルを手作業でコーディングしていますが、一般にカーネル プルーニング技術ほど効果的ではありません。
2. 既存のカーネル プルーニング テクノロジの制限
既存のカーネル プルーニング テクノロジーには、主に 5 つの制限があります。ブートフェーズ中は表示されません。既存の手法は、ftrace に依存してカーネルのブート後にのみ開始できるため、ブート フェーズ中にどのようなカーネル コードがロードされるかを観察する方法がありません。重要なモジュールがカーネルから欠落している場合、カーネルはブートに失敗することが多く、カーネルの多くの機能特徴はブート フェーズを観察することによってのみ取得できます。さらに、パフォーマンスとセキュリティの問題も起動時にのみロードされるため (たとえば、マルチコア サポートの CONFIGSCHEDMC と CONFIGSECURITYNETWORK)、パフォーマンスとセキュリティが低下します。
アプリケーション展開の迅速なサポートが不足している。既存のツールを使用して、カーネルに合わせて調整された新しいアプリケーションをデプロイするには、トレース、分析、アセンブルの 3 つのステップを完了する必要があります。このプロセスには時間がかかり、数時間、場合によっては数日かかる場合があり、アプリケーション展開の機敏性が妨げられます。
粒径は粗めです。 ftrace を使用すると、カーネル コードを関数レベルでしかトレースできず、関数内のコードに影響を与える構成オプションをトレースするには粒度が粗すぎます。
不完全な報道。動的トレースが使用されるため、カバレッジを最大化するためにカーネルのコード実行を駆動するにはアプリケーションのワークロードが必要です。ただし、ベンチマーク カバレッジは難しく、トレース中に検出されないカーネル コードがアプリケーションにある場合、トリミングされたカーネルが実行時にクラッシュする可能性があります。
実行の依存関係には区別がなく、冗長性が存在する可能性があります。実際には実行する必要がないコードでも、カーネル機能に含まれる場合があります。たとえば、2 番目のファイル システムを初期化する場合があります。
最初の 3 つの制限は克服可能であり、設計とツールを改善することで対処できますが、最後の 2 つの制限は避けられず、特定のテクノロジを超えた努力が必要です。
3. Linux カーネル構成
3.1 構成オプション
カーネル構成は、一連の構成オプションで構成されます。カーネル モジュールには複数のオプションを指定でき、それぞれが最終的なカーネル バイナリにどのコードを含めるかを制御します。
構成オプションは、C プリプロセッサによって実装されるステートメントや関数、Makefile に基づいて実装されるオブジェクト ファイルなど、カーネル コードのさまざまな粒度を制御します。 C プリプロセッサは #ifdef/#ifndef に基づいてコード ブロックを選択し、構成オプションはマクロ定義として使用され、そのような条件付きコード ブロックがコンパイルされたカーネルに含まれるかどうかをステートメント粒度または関数粒度で決定します。 Makefile は、コンパイルされたカーネルに特定のオブジェクト ファイルが含まれるかどうかを判断するために使用されます。たとえば、CONFIG_CACHEFILES は Makefile の構成オプションです。
ステートメントレベルの構成オプションは、既存のカーネル調整ツールで使用される関数レベルのトレースでは識別できません。実際、Linux 4.14 の C プリプロセッサの約 30% はステートメント レベルのオプションです。
カーネル コードと機能機能の急速な成長に伴い、カーネル内の構成オプションの数も急速に増加しており、Linux カーネル 3.0 以降には 10,000 を超える構成オプションがあります。
3.2. 設定言語
Linux カーネルは、KConfig 構成言語を使用して、コンパイルされたカーネルにどのコードを含めるかをコンパイラーに指示し、構成オプションとそれらの間の依存関係を定義できるようにします。
KConfig の構成オプションの値は、bool、tristate、または constant です。 bool は、コードが静的にカーネル バイナリにコンパイルされるか、除外されることを意味します。一方、 tristate は、コードをロード可能なコア モジュール、つまり実行時にロードできるスタンドアロン オブジェクトにコンパイルできるようにします。 constant は、カーネル コード変数の文字列または数値を提供できます。 1 つのオプションが別のオプションに依存する可能性があり、KConfig は依存関係を再帰的に選択およびキャンセルする再帰的なプロセスを使用します。最終的なカーネル構成には有効な依存関係がありますが、ユーザー入力とは異なる場合があります。
3.3. 設定テンプレート
Linux カーネルには、多数の手作りの構成テンプレートが付属しています。ただし、構成テンプレートはハードコーディングされており、手動による介入が必要なため、さまざまなハードウェア プラットフォームに適応できず、アプリケーションのニーズを理解できません。たとえば、tinyconfig で構築されたカーネルは、標準のハードウェアで起動することができず、ましてや他のアプリケーションをサポートすることもできません。一部のツールは localmodconfig を最小構成として扱いますが、localmodconfig には静的構成テンプレートと同じ制限があり、制御ステートメント レベルまたは関数レベルの C プリプロセッサ構成オプションが有効にならず、ロード可能なカーネルも処理されません。
kvmconfig および xenconfig テンプレートは、KVM および Xen 上で実行されるカーネル用にカスタマイズされています。これらは、基盤となる仮想化やハードウェア環境などのドメイン知識を提供します。
3.4. クラウドでの Linux カーネル設定
Linux はクラウド サービスにおける主要なオペレーティング システム カーネルであり、クラウド プロバイダーは通常の Linux カーネルをある程度放棄しています。クラウド ベンダーによるカスタマイズは、ロード可能なカーネル モジュールを直接削除することで実現されることがよくありますが、カーネル モジュールのバイナリを手動で削除する場合の問題は、依存関係に違反する可能性があることです。重要なのは、アプリケーションの要件に基づいてコアをさらにカスタマイズできることです。たとえば、Amazon FireCracker カーネルは、HTTPD をターゲット アプリケーションとして使用する、サービスとしての機能向けに設計された小さな仮想マシンであり、機能とパフォーマンスの向上を確保しながら、カーネルの調整を大幅に最小限に抑えることができます。
4. カーネルプルーニングに関する考え
制限 1 に関して、QEMU からの命令レベルのトレースを使用してブート フェーズの可視性を実現することは可能ですか?このようにして、カーネル コードを追跡し、カーネル構成オプションにマッピングすることができます。起動フェーズは起動可能なカーネルを生成するために重要であるため、ハイパーバイザーが提供するトレース機能を使用して、エンドツーエンドの可観測性を獲得し、安定したカーネルを生成します。
制限 2 については、NLP 深層学習の経験に基づいて、オフラインとオンラインの方法を組み合わせて使用できます。ターゲット アプリケーションのセットが与えられると、アプリ構成をオフラインで直接生成し、ベースライン構成と組み合わせて、完全なカーネル構成を形成し、トリミングされたカーネルが得られます。このコンポーザビリティにより、アプリケーション構成や以前に構築されたファイル (カーネル モジュールなど) を再利用して、新しいカーネルを段階的に構築できます。ターゲット アプリケーションの構成がわかっている場合、カーネル プルーニングは数十秒で完了できます。
制限 3 については、命令レベルのトレースを使用すると、関数の内部機能特性を制御するカーネル構成オプションを解決できます。命令レベルのトレースのオーバーヘッドは、テスト スイートおよびパフォーマンス ベンチマークの実行には許容されます。
制限 4 については、ダイナミック トレーシングを使用する場合の基本的な制限は、テスト スイートとベンチマークが不完全であることです。オープン ソース アプリケーションのテスト スイートの多くは、コード カバレッジが低いです。さまざまなワークロードを組み合わせてアプリケーションを駆動すると、この制限をある程度緩和できます。
制限 5 については、ドメイン固有の情報を使用して、ベースライン カーネルで実行されるが、実際のデプロイメントの実行時には不要なカーネル モジュールを削除することで、カーネルをさらに読み込むことができます。 Xen と KVM を例に挙げると、xenconfig および kvmconfig 構成テンプレートに基づいてカーネル サイズをさらに縮小できます。アプリケーション指向のカーネル プルーニングでは、カーネル サイズをさらに縮小し、カーネル コードを広範囲にカスタマイズすることもできます。
5 カーネル調整フレームワークに関する予備調査
カーネル調整フレームワークの原則は変わっていません。ターゲット アプリケーションのワークロードのカーネル使用状況を追跡して、必要なカーネル オプションを決定することは変わりません。
5.1 カーネル クリッピング フレームワークのコア機能
カーネル クリッピング フレームワークには、おそらく次のような特徴があります:
エンドツーエンドの可視性。ハイパーバイザーの可視性を活用してエンドツーエンドの観察を実現し、カーネルのブート フェーズとアプリケーションのワークロードを追跡し、QEMU に基づいた Linux カーネルの調整フレームワークの構築を試みることができます。
構成可能性。中心的なアイデアは、特定のデプロイメント環境でカーネルを起動するためと、ターゲット アプリケーションに必要な構成オプションの両方のために、カーネル構成をいくつかの構成セットに分割することで結合できるようにすることです。構成セットは、ベースライン構成とアプリケーション構成の 2 つのタイプに分類されます。ベースライン構成は、特定のハードウェアで起動するために必要な最小構成セットである必要はなく、ブート フェーズ中に追跡される構成オプションのセットです。ベースライン構成を 1 つ以上のアプリケーション構成と組み合わせて、最終的なカーネル構成を作成できます。
再利用性。ベースライン構成とアプリケーション構成は両方ともデータベースに保存でき、展開環境とアプリケーション バイナリが変更されない限り再利用できます。この再利用性により、トレース ワークロードの繰り返し実行が回避され、構成セットの作成が 1 回限りのジョブになります。
迅速なアプリケーション展開をサポートします。デプロイメント環境とターゲット アプリケーションが与えられると、カーネル調整フレームワークはベースライン構成とアプリケーション構成を効率的に取得し、それらを組み合わせて必要なカーネル構成を作成し、その結果の構成を使用して古いカーネルを構築できます。
低レベルのコード パターンに基づいて構成オプションを識別するための、きめ細かい構成トレース、プログラム カウンター ベースのトレース。
5.2 カーネル クリッピング フレームワークのアーキテクチャ
カーネル調整フレームワークにはオフライン システムとオンライン システムの両方が必要であり、そのアーキテクチャは次の図に示すとおりです。
構成トラッカーは、オフライン システムを通じて、展開環境とアプリケーションに必要な構成オプションを追跡および記録するために使用されます。構成ジェネレーターは、これらのオプションをベースライン構成オプションとアプリケーション構成オプションに処理し、構成データベースに保管します。
オンライン システムを通じて、構成コンビネーターはベースライン構成とアプリケーション構成を使用してターゲット カーネル構成を生成し、カーネル ビルダーはカスタマイズされた Linux カーネルを生成します。
5.3 カーネル調整フレームワーク実装の実現可能性
構成の追跡
カーネル調整フレームワークの構成トラッカーは、PC レジスタを使用して実行中の命令のアドレスをキャプチャし、ターゲット アプリケーションによって駆動されるカーネル実行中の構成オプションを追跡します。追跡された PC が他のプロセス (バックグラウンド サービスなど) ではなく、ターゲット アプリケーションに属していることを確認するために、カスタマイズされた init スクリプトを使用できます。このスクリプトは、他のアプリケーションを起動せず、ファイル システム /tmp、/ のみをマウントします。 proc と /sys を実行し、ネットワーク インターフェイス (lo と eth0) を有効にし、最後にカーネルの起動直後にアプリケーションを起動します。
同時に、アドレスがソース コードに正しくマップされ、トリミングされたカーネルでも引き続き使用できるように、カーネル アドレス空間構成のランダム ロードを無効にすることが必要になる場合があります。次に、PC をソース コード ステートメントにマッピングします。ロード可能なカーネル モジュールには追加の処理が必要です。/proc/module を使用して、ロードされた各カーネル モジュールの開始アドレスを取得し、これらの PC をカーネル モジュール バイナリ内のステートメントにマップできます。代替手段は、localmodconfig を利用することです。ただし、localmodconfig は、モジュール粒度レベルでの情報のみを提供します。
最後に、ステートメントを構成に帰属させます。 C プリプロセッサ ベース モードの場合、C ソース ファイルが解析されてプリプロセッサ ディレクティブが抽出され、それらのディレクティブ内のステートメントが実行されるかどうかがチェックされます。 Makefile ベース モードの場合、オブジェクト ファイルの粒度で構成オプションを選択する必要があるかどうかを決定します。たとえば、対応するファイル (bind.o、achefiles.o、または daemon.o) のいずれかを使用する場合は、CONFIG_CACHEFILES を選択する必要があります。
構成の生成
ベースライン構成とアプリケーション構成はオフライン システムで生成されます。スタートアップフェーズの終了をどのように判断するか?空のスタブ関数は、mmap を使用して事前定義されたアドレス セグメントにマッピングできます。上記の init スクリプトは、ターゲット アプリケーションを実行する前にスタブ関数を呼び出すため、PC 内の事前定義されたアドレスに基づいてブート フェーズの終了を識別することができます。痕跡。
カーネル調整フレームワークはアプリケーションから構成オプションを取得し、ブートフェーズ中に観察されたハードウェア関連のオプションをフィルターで除外します。これらのハードウェア機能は、カーネル ソース コード内の位置に基づいて定義されます。ハードウェア関連のオプションは、必要に応じて新しいデバイス ドライバーをロードするなど、アプリケーションの実行中にのみ観察される可能性を排除できません。
構成アセンブリ
ベースライン構成を 1 つ以上のアプリケーション構成と組み合わせると、カーネルの構築に使用される最終構成が生成されます。まず、すべての構成オプションが初期構成にマージされ、次に SAT ソルバーを使用してそれらの間の依存関係が解決されます。構成の依存関係をブール充足可能性問題としてモデル化してみてください。有効な構成とは、構成オプション間で指定されたすべての依存関係を満たすものです。 KConfig は、選択されたすべてのオプションが含まれていることを保証するのではなく、満たされていない依存関係の選択を解除するため、カーネル構成のモデル化は SAT ソルバーに基づいています。
カーネルビルド
KBuild for Linux は、アセンブルされた構成オプションに基づいてカスタマイズされたカーネルを構築します。最新の make を使用した増分ビルドは、ビルド時間を最適化し、冗長なコンパイルを避けるために以前のビルド結果 (オブジェクト ファイルやカーネル モジュールなど) をキャッシュすることもできます。構成変更が発生すると、構成オプションに変更を加えたモジュールのみが再構築され、他のファイルは再利用できます。
6.概要
オペレーティング システム カーネルの不安定性、適時性の低さ、整合性の問題、および手動介入の必要性のため、Linux カーネル プルーニング テクノロジは広く使用されていません。既存のテクノロジーの限界を理解した後、これらの問題を解決できる可能性のある Linux カーネル調整フレームワークの提案を試みます。
以上がLinux カーネルプルーニングフレームワークに関する予備調査の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。