最近、Mac OS Xは、x86カーネルがロードされていても、実際には64ビット(x64)アプリケーションを実行できることがわかりました。それは私にとって初めて衝撃的でした。
しかし、x64互換のCPUでシステムが稼働していると、プロセスを管理しているカーネルに関係なく、x64アプリケーションを実行できないのは本当に奇妙だと気づきました。本当に大変ですか?いまいましいアプリをメモリにロードし、CPU操作ポインタを最初のバイトに設定するだけです。パイのように簡単です。
私が想像できるように、それを行うための唯一の障壁は、ある種の「実行可能ヘッダー」です。残念ながら、私はWindowsアーキテクチャとバイナリ構造にあまり慣れていないので、ここでさらに説明が必要です。
事実上のUNIXライクなOSバイナリヘッダー標準ELFには、兄弟ELF64があります。これは(ドキュメント ここ で説明されているように)ELF32とあまり違いはありませんが、32ビットカーネルは実行できません。 x64コード。はい、このプログラムはx64ライブラリにリンクされている可能性があり、それらをコピーして/ usr/lib64フォルダーに貼り付けたところを想像してみてください。しかし、それは役に立たないと確信しています、なぜですか?
そして最後に、Mac OS Xカーネルの何が特別なので、使用されるプログラム命令セットについて心配する必要はありませんか? Mac OS Xには、両方のカーネルの実行可能ファイルヘッダーに適したユニバーサルな機能があります。そのため、アプリをメモリにロードして、CPUに「ここから実行してください。それが何を意味するかは関係ありません」と言うことができますか?
追伸:私はこの質問をどこに置くかについて本当によく考えました:stackoverflow.comまたはsuperuser.comで、トピックはおそらくOS固有のものであるため、ここに置くことにしました。
本当の問題は、他のいくつかのオペレーティングシステムが32ビットカーネルで64ビットバイナリを実行できない理由です。それが不可能になる根本的な理由はありません。基盤となるプロセッサアーキテクチャは、64ビット命令セット(AMD64、別名x86-64)と32ビット命令セット(i386)の両方をサポートし、2つを一緒に使用することに制限はありません(特に、 「32ビットモード」とは別の「64ビットモード」。単一の ロングモード があり、i386と「ネイティブ」AMD64セットの両方からの命令を許可します。
32ビットカーネルで64ビットアプリケーションを実行するには、カーネル空間への32ビットポインターと一緒にユーザースペースへの64ビットポインターを管理する必要があるため、カーネル内でもう少し作業が必要です。カーネル内で渡されるすべてではないにしてもほとんどのポインターは、カーネルスペースへのポインターであるか、ユーザースペースへのポインターであることがわかっているため、サイズが異なっていても問題はありません。主な問題は、プロセスメモリ、カーネルメモリ、およびさまざまなハードウェア(RAMを含む)で使用されるメモリの値の範囲が異なるユニバーサルポインタタイプの可能性を先取りすることですが、これは最近の32ビットカーネルでは不可能です。とにかくPCクラスのハードウェア上(4GB以上のRAMがある場合、または2GBのRAM + 2GBのプロセススペースとカーネルメモリなど)をマップする場合は、マップできる必要がありますとにかく32ビット以上のアドレス)。
あなたが引用している ウィキペディアの記事 によると、OSXには64ビットカーネルが搭載される前にAMD64プロセッサでAMD64プロセスを実行する機能がありました。 Solarisは、カーネルが32ビットか64ビットか(どちらも使用可能)に関係なく、AMD64プロセッサ上でi386とAMD64の実行可能ファイルを無差別に混合します。
Linux、FreeBSD、NetBSD、Windowsなどの他のオペレーティングシステムは、(64ビット)AMD64カーネルでi386プロセスを実行できますが、32ビットカーネルでAMD64プロセスを実行することはできません。さらに他のオペレーティングシステムは、AMD64とi386を完全に異なるアーキテクチャとして扱います(OpenBSDなど)。
詳細を説明するのにx86_64アーキテクチャに精通していませんが、基本的には、カーネルとユーザースペース間のコンテキスト切り替えの一部としてCPUが64ビットモードと互換性(32ビット)モードの間で切り替えられます。プログラム。これは、64ビットカーネルで32ビットプログラムを実行する場合とほぼ同じですが、逆になります。
ところで、OS XはELFバイナリ形式を使用せず、 Mach-O バイナリを使用します。 Mach-O形式ではマルチアーキテクチャ(「ユニバーサル」)バイナリが許可されているため、プログラム(さらに言えばカーネル)は32ビットと64ビットの両方で提供できます(およびPPCおよびPPC64と...)、OSはロード時にロードするバージョン(したがって、それを実行するモード)を選択できます。バイナリでfile
コマンドを使用して、それがどのフォーマットであるかを確認できます。たとえば、OS Xv10.5に同梱されているChessアプリケーションは次のとおりです。
$ file Applications/Chess.app/Contents/MacOS/Chess
Applications/Chess.app/Contents/MacOS/Chess: Mach-O universal binary with 4 architectures
Applications/Chess.app/Contents/MacOS/Chess (for architecture ppc): Mach-O executable ppc
Applications/Chess.app/Contents/MacOS/Chess (for architecture ppc64): Mach-O 64-bit executable ppc64
Applications/Chess.app/Contents/MacOS/Chess (for architecture i386): Mach-O executable i386
Applications/Chess.app/Contents/MacOS/Chess (for architecture x86_64): Mach-O 64-bit executable x86_64
そして、これが可能であると疑う人への注意:OS Xはv10.4以降の64ビットプログラムをサポートしていましたが(APIサポートは制限されています)、v10.6まで64ビットカーネルは含まれていませんでした(それでも、カーネルは、ほとんどのモデルでデフォルトで32ビットモードで実行されていました)。詳細については、 Appleの64ビット移行ガイド を参照してください。 32ビットカーネルで10.6を実行しているMacBookProからこれを投稿しています(この特定のモデルでは64ビットはサポートされていません)が、アクティビティモニターによるとのみ64ビットモードで実行されていないプロセスはkernel_taskです。
Macは、32ビットカーネル上での64ビットアプリの実行をサポートしています。これは、多段階の計画がまさにそれを実行するためです。
そのため、OS Xは64ビットアプリをできるだけ早くサポートし、ドライバーの状況のために32ビットカーネルをできるだけ長く実行し続けます。 (カーネルのビット数は、大量のRAM-ページテーブルもメモリを消費します-を管理しようとする場合にのみ要因になります-64ビットカーネルに切り替えると、パフォーマンス上の利点がいくつかあります。 )しかし、Appleは確かに物を落とすことに恥ずかしがり屋ではありません。
本当の問題は、なぜWindowsとLinuxが同じことをしなかったのかということです。 Windowsの場合、Win64での最初の試みはItaniumであったと考えてください。これは、まったく異なります。しかし、最終的な答えは、過去数十年の間通常持っているものに要約されるかもしれません: 物事を完全に正しい方法で行わなかった :の多くのサードパーティプログラムとの互換性
OS Xの64ビット実装は、32ビットバージョンと64ビットバージョンを異なるインストールメディアに保存された2つの異なるオペレーティングシステムとして扱うWindowsの実装とは大きく異なります。これは主に、Windowsと古いアプリケーションとの互換性を維持するために行われます。System32フォルダーなどを移動したり名前を変更したりすると、そこにあると期待していたプログラムが壊れてしまいます。その結果、2つは分離され、アップグレードすらできなくなります。 32ビットWindowsと64ビットWindows間のパス。このため、またWindowsアプリケーションとドライバーには通常32ビットと64ビットのバージョンが異なるため、Windowsの64ビットへの移行は少し難しく、ユーザーには少しわかりやすくなっています。
Mac側 と Windows側 の両方で、64ビット遷移に関する背景情報がたくさんあります。 (これらのリンクは、各シリーズの記事の最後にあります。必ず最初に戻ってください。)
Linuxの話はわかりませんが、Linusがそれについて強い意見を持っていたと想像してください。
システムがx64互換で稼働している場合、プロセスを管理しているカーネルに関係なく、x64アプリケーションを実行できないのは本当に奇妙だと気づきました。本当に大変ですか?いまいましいアプリをメモリにロードし、CPU操作ポインタを最初のバイトに設定するだけです。パイのように簡単です。
重要な部分が欠けています。アプリは、オペレーティングシステムによって提供される関数とサービスに対してAPI呼び出しを行います。 64ビットアプリが64ビットポインターを32ビットオペレーティングシステムに送信すると、問題が発生するはずです。
どちらの方法でも問題なく機能させるには、OSが関数をオーバーロードし、各関数の64ビットバージョンと32ビットバージョンの両方を提供する必要があると思います。カーネルごとに、「オフ」関数(32ビットカーネルでは64ビット関数、64ビットカーネルでは32ビット関数)は、呼び出しを32ビットセーフに変換してからネイティブ関数を再呼び出しするスタブになります。