web-dev-qa-db-ja.com

Linuxを別のプラットフォーム要件に移植する

Linuxが利用可能であり、X86、ARM、PowerPCなど、さまざまなプラットフォームに移植されていることは知っています。

しかし、移植に関して、正確には何が必要ですか?

LinuxはCで書かれたソフトウェアであると私は理解しています。したがって、元々LinuxをX86からARMなどに移植する場合、コンパイラーでコードを再コンパイルするだけの問題ではありません。特定のターゲットアーキテクチャ?

さまざまな周辺機器用のデバイスドライバーを別にしておくと、Linuxを新しいアーキテクチャに移植するときに他に何をする必要がありますか。コンパイラーがすべてを処理するわけではありませんか?

28
Engineer999

Linuxカーネルのコードの大部分はCで記述されていますが、そのコードには、実行中のプラットフォームに非常に固有であり、それを考慮する必要がある部分がまだたくさんあります。

この1つの特定の例は仮想メモリであり、ほとんどのアーキテクチャ(ページテーブルの階層)で同様に機能しますが、各アーキテクチャの特定の詳細(各アーキテクチャのレベル数など)があり、これはx86でも増加しています新しいより大きなチップの導入。)Linuxカーネルコードは、これらの階層のトラバースを処理するマクロを導入します。これにより、ページテーブルのレベルが少ないアーキテクチャでコンパイラーによって省略できます(そのため、コードはCで記述されていますが、アーキテクチャの詳細を考慮。)

他の多くの領域は各アーキテクチャに非常に固有であり、Arch固有のコードで処理する必要があります。ただし、これらのほとんどにはアセンブリ言語のコードが含まれます。次に例を示します。

  • コンテキスト切り替え:コンテキスト切り替えには、切り替え対象のプロセスのすべてのレジスタの値を保存し、CPUにスケジュールされたプロセスの保存されたセットからレジスタを復元することが含まれます。レジスタの数とセットでさえ、各アーキテクチャに非常に固有です。このコードは通常、アセンブリに実装されており、レジスタへの完全なアクセスを可能にし、また、可能な限り高速に実行されるようにします。これは、コンテキスト切り替えのパフォーマンスがシステムにとって重要になる可能性があるためです。

  • システムコール:ユーザー空間コードがシステムコールをトリガーできるメカニズムは、通常、アーキテクチャに固有です(場合によっては特定のCPUモデルにも固有です。たとえば、IntelとAMDがそのための異なる命令を導入しましたが、古いCPU)これらの指示が不足している可能性があるため、それらの詳細はまだ一意です。)

  • Interrupt Handlers:割り込み(ハードウェア割り込み)の処理方法の詳細は通常プラットフォーム固有であり、通常、プラットフォームで使用されている特定の呼び出し規約を処理するには、アセンブリレベルの接着剤が必要です。また、割り込みを有効/無効にするためのプリミティブは通常、プラットフォーム固有であり、アセンブリコードも必要です。

  • Initialization:初期化が行われる方法の詳細には、通常、プラットフォームに固有の詳細も含まれており、カーネルへのエントリポイントを処理するためのアセンブリコードが必要になることがよくあります。複数のCPU(SMP)を備えたプラットフォームでは、他のCPUをオンラインにする方法の詳細も通常、プラットフォーム固有です。

  • Locking Primitives:ロックプリミティブ(スピンロックなど)の実装には、通常、プラットフォーム固有の詳細も含まれます。これは、一部のアーキテクチャが異なるCPU命令を提供(または優先)して、それらを効率的に実装するためです。アトミック操作を実装するものもあれば、アトミックにテスト/更新できるcmpxchgを提供するものもあります(ただし、別のライターが最初に取得した場合は失敗します)。CPU命令に「ロック」修飾子を含めるものもあります。これらには、アセンブリコードの記述も含まれます。

カーネル(または具体的には、Linuxカーネル)でプラットフォーム固有またはアーキテクチャ固有のコードが必要な他の領域がおそらくあります。カーネルソースツリーを見ると、Arch/以下にアーキテクチャ固有のサブツリーがあります。 include/Arch/には、この例が他にもあります。

たとえば、各アーキテクチャで使用可能なシステムコールの数は異なり、一部のシステムコールは一部のアーキテクチャに存在し、他には存在しないことがわかります。 (x86でも、32ビットと64ビットのカーネルでは、syscallのリストが異なります。)

要するに、カーネルがプラットフォームに固有であることに注意する必要がある多くの場合があります。 Linuxカーネルはそれらのほとんどを抽象化しようとするため、高レベルのアルゴリズム(メモリ管理やスケジューリングの動作など)をCに実装して、すべてのアーキテクチャで同じ(またはほとんど同じ)動作をさせることができます。

57
filbranden

Linuxカーネルの移植に加えて、「ユーザースペース」に application binary interface (ABI)を定義する必要がありますユーザー空間ソフトウェアスタックの最下層のプログラムとポート。 Linuxは通常、GNUプロジェクトからの低レベルのユーザー空間コンポーネントとともに使用されます。最も重要なものは次のとおりです。

  • Cコンパイラ、アセンブラ、およびリンカー: [〜#〜] gcc [〜#〜] および GNU Binutils 。まったく新しいCPUアーキテクチャでは、カーネル自体をCプログラムとしてコンパイルする必要があるため、カーネルの移植を開始する前にこのソフトウェアを移植する必要があります。 OSカーネルとしてLinuxだけでなく、プラットフォームのCPUの「バックエンド」サポートがすでにある場合は、実行する作業が大幅に少なくなり、カーネルが稼働するまでほとんどの作業を延期することで回避できる可能性があります。ランニング。
  • Cランタイムライブラリ: " GNU libc "。このライブラリには、システムコールをして作成するコードが含まれており、それ以外の場合はカーネルと直接対話します。
  • 「外部関数インターフェース」ライブラリ libffi は、多くの高級言語インタープリターの必須コンポーネントであり、に必要な残りのいくつかのタスクの1つを実行します少量の手書きのアセンブリ言語。

他の多くのソフトウェアには、オプションのプラットフォーム依存コンポーネントがあります。たとえば、新しいCPUアーキテクチャ用に [〜#〜] nss [〜#〜] および OpenSSL に対して手動で最適化された暗号プリミティブを記述した場合、Webブラウジングは大幅に高速になります。 、および IonMonkey および V8 のジャストインタイムコンパイルバックエンド。しかし、これらは新しいプラットフォームを立ち上げるために不可欠ではありません。

10
zwol

移植するハードウェアについてカーネルに伝える必要があります。カーネルの仕事はハードウェアと直接インターフェースすることなので、適切に機能するために、カーネルはCPU、発振器(クロック)、およびさまざまな種類のシリアルポート(SPI、CAN、 I2Cなど)。

昔は、ドライバーが機能するために使用するプラットフォーム固有のコードを記述することでこれを実現していました。最近では、これは デバイスツリー定義 と書くことで行われます。

1
RubberDuck