Linux 構成/ビルド システムがどのように機能するかを深く理解します。 Linux カーネル構成/ビルド システム (Kconfig/kBuild とも呼ばれます) は、Linux カーネル コードが Git に移行されて以来、長い間存在しています。しかし、サポート インフラストラクチャとしてはあまり注目されておらず、日常業務でそれを使用しているカーネル開発者でさえ、実際にはそれについて考えたことがありません。 Linux カーネルがどのようにコンパイルされるかを探るために、この記事では Kconfig/kBuild の内部を詳しく調べ、.config ファイルと vmlinux/bzImage ファイルがどのように生成されるかを説明し、依存関係を追跡するためのスマートなトリックを紹介します。 設定 カーネルを構築する最初のステップは常に構成です。 Kconfig は、Linux カーネルを高度にモジュール化およびカスタマイズ可能にするのに役立ちます。 Kconfig は、ユーザーにいくつかの構成ターゲットを提供します。
これらのターゲットの中では menuconfig が最も人気があると思います。ターゲットは、カーネルによって提供され、カーネル ビルド プロセス中に生成されるさまざまなホスト プログラムによって処理されます。一部のターゲットには GUI (ユーザーの利便性のため) がありますが、ほとんどのターゲットには GUI がありません。 kconfig 関連のツールとソース コードは、主にカーネル ソース コードの scripts/kconfig/ にあります。 scripts/kconfig/makefile から開始できます。CONF、mconf、nconf など、いくつかのホスト プログラムがあります。 conf を除いて、それぞれが GUI ベースの構成ターゲットの 1 つを担当しているため、conf がそれらのほとんどを処理します。 論理的には、Kconfig インフラストラクチャには 2 つの部分があります。1 つは構成項目を定義するための新しい言語を実装する部分 (カーネル ソース コードの Kconfig ファイルを参照)、もう 1 つは Kconfig 言語を解析して構成操作を処理する部分です。 ほとんどの構成ターゲットの内部フローはほぼ同じです (以下を参照)。 すべての構成項目にはデフォルト値があることに注意してください。 最初のステップでは、ソース ルートの下の Kconfig ファイルを読み取って初期構成データベースを構築し、次に既存の構成ファイルを読み取って、この優先順位に従って初期データベースを更新します。
menuconfig またはコマンド ライン ベースの構成 (oldconfig) を介して GUI ベースの構成を実行している場合は、データベースがカスタマイズ内容で更新されます。最後に、構成データベースを .config ファイルにダンプします。 しかし、.config ファイルはカーネル ビルドの最終製品ではありません。そのため、syncconfig ターゲットが存在します。 syncconfig は以前は silentoldconfig というファイルでしたが、古い名前どおりの動作をしなかったため、名前が変更されました。また、これは内部使用用であり、ユーザー向けではないため、リストから削除されました。 syncconfig が実行する処理の例を次に示します。 syncconfig は .config を入力として受け取り、次の 3 つのカテゴリに分類される他のいくつかのファイルを出力します。 auto.conf と tristate.conf は、テキスト処理用のファイルを生成するために使用されます。たとえば、コンポーネントの makefile に次のようなステートメントがある場合があります。 autoconf.h は C 言語のソース ファイルで使用されます。 空のヘッダー ファイル include/config/ は、以下で説明する kbuild 中の構成依存関係の追跡に使用されます。 プロファイリング後、どのファイルとコード セグメントがコンパイルされていないかがわかります。 Kビルド 再帰的な make と呼ばれるコンポーネント単位の構築は、GNU では一般的なアプローチです。大規模なプロジェクトを作成および管理します。 KBuild は再帰的な make の良い例です。ソース ファイルを異なるモジュール/コンポーネントに分割することで、各コンポーネントは独自の Makefile によって管理されます。ビルドを開始すると、最上位の Makefile が各コンポーネントの makefile を正しい順序で呼び出し、コンポーネントをビルドして、最終的な実行可能ファイルに収集します。 KBuild はさまざまな種類の makefile を参照します。
最上位の makefile には archmakefile が含まれており、これは .config ファイルを読み取り、サブディレクトリに移動し、make を呼び出して、そこに定義されているルーチンの助けを借りて各コンポーネント makefile を実装します。 scripts/Makefile* は、各中間オブジェクトを構築し、すべての中間オブジェクトを vmlinux にリンクします。コア ファイル Documentation/kbuild/makefiles.txt には、これらの makefile のすべての側面が記述されています。 たとえば、x86-64 上で vmlinux を起動する方法を見てみましょう。 (イラストは Richard Y. Steven のブログに基づいています。著者の許可を得て更新および使用しています。) vmlinux に入るすべての .o ファイルは、まず変数によって表される独自の組み込み .a に入ります。 KBUILD_VMLINUX_INIT、KBUILD_VMLINUX_Main、KBUILD_VMLINUX_LIBS を収集し、それらを vmlinux ファイルに収集します。 簡略化された Makefile コードを使用して、再帰的な make が Linux カーネルでどのように実装されているかを見てみましょう。 # トップのMakefile内 vmlinux: scripts/link-vmlinux.sh $(vmlinux-deps) +$(if_changed、link-vmlinux を呼び出す) # 変数の割り当て vmlinux 依存関係 := $(KBUILD_LDS) $(KBUILD_VMLINUX_INIT) $(KBUILD_VMLINUX_MAIN) $(KBUILD_VMLINUX_LIBS) エクスポート KBUILD_VMLINUX_INIT := $(head-y) $(init-y) エクスポート KBUILD_VMLINUX_MAIN := $(core-y) $(libs-y2) $(drivers-y) $(net-y) $(virt-y) エクスポート KBUILD_VMLINUX_LIBS := $(libs-y1) KBUILD_LDS をエクスポート:= arch/$(SRCARCH)/kernel/vmlinux.lds init-y := init/ ドライバ-y := ドライバ/ サウンド/ ファームウェア/ ネット-y := ネット/ ライブラリ-y := lib/ コアy := usr/ virt-y := virt/ # 対応する組み込み.aに変換する init-y := $(patsubst %/, %/built-in.a, $(init-y)) core-y := $(patsubst %/, %/built-in.a, $(core-y)) ドライバーy := $(patsubst %/, %/built-in.a, $(drivers-y)) net-y := $(patsubst %/, %/built-in.a, $(net-y)) libs-y1 := $(patsubst %/, %/lib.a, $(libs-y)) libs-y2 := $(patsubst %/, %/built-in.a, $(filter-out %.a, $(libs-y))) virt-y := $(patsubst %/, %/built-in.a, $(virt-y)) # 依存関係を設定します。vmlinux-depsはすべて中間オブジェクトで、vmlinux-dirs # は偽のターゲットなので、このルールが適用されるたびに、vmlinux-dirsのレシピ # が実行されます。`info make` の「4.6 Phony Targets」を参照してください。 $(ソート $(vmlinux-deps)): $(vmlinux-dirs) ; # 変数 vmlinux-dirs は各組み込みのディレクトリ部分です。 vmlinux-dirs := $(patsubst %/,%,$(filter %/, $(init-y) $(init-m) \ $(コア-y) $(コア-m) $(ドライバー-y) $(ドライバー-m) \ $(net-y) $(net-m) $(libs-y) $(libs-m) $(virt-y))) # 再帰的なmakeのエントリ $(vmlinux-ディレクトリ): $(Q)$(MAKE) $(ビルド)=$@ 組み込みが必要=1 再帰的なレシピの展開、例: これは、make が scripts/Makefile.build に入り、各built-in.a のビルドを続行することを意味します。 scripts/link-vmlinux.sh の助けを借りて、vmlinux ファイルは最終的にソース ルートの下に配置されます。 vmlinux と bzImage を理解する 多くの Linux カーネル開発者は、vmlinux と bzImage の関係を明確に理解していない可能性があります。たとえば、x86-64 では次のようになります。 ソース ルート vmlinux はストリップされ、圧縮されて、piggy.S に配置され、その後、他のピア オブジェクトが arch/x86/boot/compressed/vmlinux にリンクされます。同時に、arch/x86/boot に setup.bin というファイルが生成されます。 config_x86_RELOCS に応じて、再配置情報を含むオプションの 3 番目のファイルが存在する場合があります。 カーネルによって提供される build というコマンドは、これらの 2 つ (または 3 つ) の部分を最終的な bzImage ファイルにビルドします。 依存関係の追跡 KBuild は 3 種類の依存関係を追跡します。
最初のものはわかりやすいですが、2番目と3番目はどうでしょうか?カーネル開発者は次のようなコード スニペットをよく目にします。 #ifdef CONFIG_SMP __boot_cpu_id = CPU; #終了 CONFIG_SMP が変更された場合は、このコードを再コンパイルする必要があります。ソース ファイルをコンパイルするために使用するコマンド ラインも重要です。コマンド ラインが異なると、オブジェクト ファイルも異なる可能性があるためです。 .C ファイルが #include ディレクティブを介してインクルードされる場合、次のようなルールを記述する必要があります。 main.o: 定義.h レシピ... 大規模なプロジェクトを管理する場合、このようなルールが多数必要になりますが、どれも面倒になる可能性があります。幸いなことに、最近の C コンパイラのほとんどは、ソース ファイル内の #include 行を調べることで判別できます。 GNUコンパイラコレクション(GCC)の場合は、コマンドライン引数を追加するだけです:-MD depfile # scripts/Makefile.lib内 c_flags = -Wp、-MD、$(depfile) $(NOSTDINC_FLAGS) $(LINUXINCLUDE) \ -include $(srctree)/include/linux/compiler_types.h \ $(__c_flags) $(modkern_cflags) \ $(ベース名フラグ) $(モッド名フラグ) これにより、次の内容の .D ファイルが生成されます。 init_task.o: init/init_task.c include/linux/kconfig.h \ include/generated/autoconf.h include/linux/init_task.h \ インクルード/linux/rcupdate.h インクルード/linux/types.h \ ... ホスト プログラム fixdep は、他の 2 つの依存関係を取得して処理します。 depfile はコマンド ラインを入力として受け取り、ターゲットのコマンド ラインとすべての前提条件 (構成を含む) を記録する Makefile 構文の .cmd ファイルを出力します。次のようになります: # ターゲットをコンパイルするために使用するコマンドライン cmd_init/init_task.o := gcc -Wp,-MD,init/.init_task.od -nostdinc ... ... # 依存ファイル deps_init/init_task.o := \ $(ワイルドカード include/config/posix/timers.h) \ $(ワイルドカード include/config/arch/task/struct/on/stack.h) \ $(ワイルドカード include/config/thread/info/in/task.h) \ ... include/uapi/linux/types.h \ arch/x86/include/uapi/asm/types.h \ include/uapi/asm-generic/types.h \ ... .cmd ファイルは再帰ビルド プロセスに含まれ、すべての依存関係情報を提供し、ターゲットを再構築するかどうかを決定するのに役立ちます。 その秘密は、Fixdep が depfile (.d ファイル) を解析し、その中のすべての依存関係ファイルを解析し、すべての config_strings のテキストを検索し、それらを対応する空のヘッダー ファイルに変換し、それらをターゲットの前提条件に追加することです。構成が変更されるたびに、対応する空のヘッダー ファイルも更新されるため、kbuild はその変更を検出し、それに依存するターゲットを再構築できます。コマンドラインも記録されるため、前回のコンパイルパラメータと現在のコンパイルパラメータを簡単に比較できます。 将来に向けて Kconfig/kbuild は、2017 年初頭に新しいメンテナーである山田正弘が参加するまで長い間変更されていませんでしたが、現在 KBuild は再び活発に開発されています。この記事の内容と異なるものがすぐに見つかったとしても驚かないでください。 要約する 以上がこの記事の全内容です。この記事の内容が皆様の勉強や仕事に何らかの参考学習価値をもたらすことを願います。123WORDPRESS.COM をご愛顧いただき、誠にありがとうございます。これについてもっと知りたい場合は、次のリンクをご覧ください。 以下もご興味があるかもしれません:
|
>>: MySQL データベースを最適化する 8 つの方法の詳細な説明 (必読の定番)
目次MySQLがmy.cnfを読み込む順序1. mysql.server の起動方法2. mysql...
mysql-5.7.17 のインストールについては記事の下部で紹介されているので、参考にしてください...
目次仮想DOMとは何ですか?なぜ仮想DOMが必要なのでしょうか?仮想 DOM はどのようにして実際の...
目次TomcatをインストールするTomcat 圧縮パッケージをダウンロードTomcatには3つの主...
序文現在、私はコースウェア PPT のオンライン プレビューを必要とする高品質のコースに取り組んでい...
目次JDKをダウンロードしてインストールするTomcat 圧縮パッケージをダウンロードTomcatの...
オーディオおよびビデオ ファイルを保存するためのディスク寿命を延ばすには、ディスクをフォーマットする...
設定は非常にシンプルですが、毎回確認しないといけないので、記録だけ残しておきます。 1. インストー...
monaco-editor-vueの公式ソースコードは次のとおりです。インデックス 'mon...
MariaDB データベース管理システムは MySQL のブランチであり、主にオープンソース コミュ...
目次定義2. 使用シナリオ3. 例を挙げる4. コーディング定義オブザーバー パターンは 1 対多の...
Go は、シンプルで信頼性が高く、効率的なソフトウェアを簡単に構築できるオープンソース プログラミン...
1. 新機能MySQL 5.7 はエキサイティングなマイルストーンです。デフォルトの InnoDB ...
1. インデックスの重要性インデックスは、列に特定の値を持つ行をすばやく見つけるために使用されます。...
この記事では、VMware仮想マシンのNAT構成プロセスを詳しく説明します。具体的な内容は次のとおり...