![Linuxを別のプラットフォームに移植するための要件[閉じる]](https://linux33.com/image/149025/Linux%E3%82%92%E5%88%A5%E3%81%AE%E3%83%97%E3%83%A9%E3%83%83%E3%83%88%E3%83%95%E3%82%A9%E3%83%BC%E3%83%A0%E3%81%AB%E7%A7%BB%E6%A4%8D%E3%81%99%E3%82%8B%E3%81%9F%E3%82%81%E3%81%AE%E8%A6%81%E4%BB%B6%5B%E9%96%89%E3%81%98%E3%82%8B%5D.png)
私はLinuxが利用可能であり、X86、ARM、PowerPCなどのさまざまなプラットフォームに移植されたことを知っています。
それでは、移植に正確に何が必要ですか?
私の理解は、LinuxがC言語で書かれたソフトウェアであるということです。それでは、最初にLinuxをX86からARMまたは他のプラットフォームに移植するときに、特定のターゲットアーキテクチャに適したコンパイラでコードを再コンパイルする必要はありませんか?
さまざまな周辺機器用のデバイスドライバを別々に設定し、Linuxを新しいアーキテクチャに移植するときに実行する必要がある追加の作業は何ですか?コンパイラは私たちのためにすべてを処理しませんか?
答え1
LinuxカーネルのコードのほとんどはCで書かれていますが、コードの多くはまだ実行されているプラットフォームに非常に具体的であるため、これを考慮する必要があります。
特別な例は、ほとんどのアーキテクチャ(ページテーブル階層)で同様の方法で動作する仮想メモリです。ただし、各アーキテクチャには特定の詳細があります(たとえば、各アーキテクチャのレベル数、またはx86ではこれも増加しています)。 Linuxカーネルコードはこれらの階層ナビゲーションを処理するためのマクロを導入し、ページテーブルレベルが少ないアーキテクチャでは、コンパイラはこれらのマクロを無視できます。したがって、コードはCで書かれていますが、アーキテクチャの詳細を考慮してください。 )
他の多くの領域は、各アーキテクチャに対して非常に具体的であり、アーキテクチャ固有のコードを使用して処理する必要があります。しかし、ほとんどはアセンブリ言語コードに関連しています。例は次のとおりです。
コンテキストスイッチ:コンテキスト切り替えには、切り替え中のプロセスのすべてのレジスタ値を格納し、CPUに予約されているプロセスのセーブセットからレジスタを復元することが含まれます。レジスタの数とセットも、各アーキテクチャによって非常に異なります。このコードは通常、レジスタへのフルアクセスを可能にし、コンテキスト切り替え性能がシステムにとって重要であるため、できるだけ早く実行されるようにアセンブリとして実装されています。
システムコール:ユーザ空間コードがシステムコールをトリガするメカニズムは、アーキテクチャによって異なります(時には特定のCPUモデルに限定されています)。詳細は、情報はまだ一意です。)
割り込みハンドラ:割り込み(ハードウェア割り込み)の処理方法の詳細は、プラットフォームによって異なりますが、プラットフォームで使用される特定の呼び出し規則を処理するためにアセンブリレベルの接続が必要な場合があります。さらに、割り込みをイネーブル/ディセーブルにする基本的な要素はプラットフォームによって異なり、アセンブリコードも必要です。
初期化:初期化がどのように行われるかについての詳細には、プラットフォーム固有の詳細も含まれることが多く、カーネルエントリポイントを処理するためにいくつかのアセンブリコードが必要なことがよくあります。複数のCPU(SMP)を持つプラットフォームで追加のCPUをオンラインにする方法の詳細も、プラットフォームごとに異なることがよくあります。
基本要素のロック:ロックプリミティブ(スピンロックなど)の実装には、プラットフォーム固有の詳細も含まれることがよくあります。一部のアーキテクチャでは、これらの命令を効率的に実装するためにさまざまなCPU命令を提供(または優先)するためです。一部はアトミックタスクを実装し、一部はアトミックにテスト/更新できるcmpxchgを提供し(他のライターが最初に来ると失敗します)、他のものはCPUコマンドに「ロック」修飾子を含みます。これには通常、アセンブリコードの記述も含まれます。
プラットフォーム固有またはアーキテクチャ固有のコードは、カーネル(または特にLinuxカーネル)に必要な場合があります。カーネルソースツリーを見ると、それに関する追加情報と例を見つけることができるアーキテクチャ固有のサブツリーが下と下にありますarch/
。include/arch/
各アーキテクチャで使用可能なシステムコールの数が異なり、特定のシステムコールが一部のアーキテクチャにのみ存在し、他のアーキテクチャには存在しないという事実など、いくつかは本当に驚くべきものです。 (x86でも、システムコールのリストは32ビットカーネルと64ビットカーネルの間で異なります。)
簡単に言えば、カーネルはプラットフォーム固有のことについて多くを知る必要があります。 Linuxカーネルはこれらの多くを抽象化しようとするので、より高いレベルのアルゴリズム(メモリの管理や予約の仕組みなど)をCで実装し、すべてのアーキテクチャで同じ(またはほぼ同じ)方法で動作できます。
答え2
Linux カーネルを移植することに加えて、以下を定義する必要があります。アプリケーションバイナリインタフェース(ABI)「ユーザースペース」プログラムとポートのユーザースペースソフトウェアスタックの最下位層。 Linux は通常 GNU プロジェクトの下位レベルのユーザー空間コンポーネントと一緒に使用されます。
- Cコンパイラ、アセンブラ、リンカ:湾岸協力協議会そしてGNU Binutils。まったく新しいCPUアーキテクチャでは、カーネル移植を開始する前にソフトウェアを移植する必要があります。カーネル自体がCプログラムであり、コンパイルする必要があるからです。プラットフォームのCPUにすでに「バックエンド」サポートがあり、Linuxをオペレーティングシステムのカーネルとして使用していない場合は、実行する作業がはるかに少なくなり、カーネルが表示されるまでほとんどを延期できます。ランニング。
- Cランタイムライブラリ: "GNUライブラリこのライブラリにはコードが含まれています。作るシステムコールを行い、そうでなければカーネルと直接対話します。
- 「外部関数インタフェース」ライブラリ、クピー、これは多くの高級言語通訳の重要な部分であり、残りのタスクの1つを実行します。必要少量の手書きのアセンブリ言語です。
他の多くのソフトウェアには、オプションのプラットフォーム依存コンポーネントがあります。たとえば、手動で最適化された暗号化基本要素を作成すると、Web検索がはるかに高速になります。国家安全保障局そしてOpenSSL新しいCPUアーキテクチャとJIT(Just-In-Time)コンパイルバックエンドで動作します。イオン猿そしてV8。しかし、新しいプラットフォームを構築するためにこれは必須ではありません。
答え3
どのハードウェアに移植したいかをカーネルに伝える必要があります。カーネルの使命はハードウェアと直接対話するため、ハードウェアが正常に動作するためには、カーネルがCPU、発振器(時計)、さまざまなシリアルポート(SPI、CAN、I2C)などの周辺機器について知っておく必要があります。 、等。)。
以前は、ドライバが実行するために使用するプラットフォーム固有のコードを書くことでこれを行うことができました。今日は、これを次のように書いて実行します。デバイスツリーの定義。