回答:
通常のコンパイル済みプログラムはCPUで「直接実行」されますが、プログラムは真空で実行されません。
多くのプログラムは、動的にロードされる外部ライブラリ(DLLs
または.so
ライブラリ)に依存しています。それらをリンクする方法はコンパイラ/リンカー次第であり、OSごとに異なる標準があります。ただし、独自のコードをすべて提供する「静的にリンクされた」プログラムもあります。
最新のOSは、実行中のプログラムに対してコンピューターの完全な制御を提供しません。プログラムは、I / O、ハードウェアへのアクセス、信号やスリープ状態への移行などの「システムコール」に依存しています。利用可能なサービスとインターフェースはOSによって定義されます。OSは、プログラムが使用を許可されるシステムの部分(メモリ、レジスタ、割り込み)も制御します。
画面上に自分自身を描画するには、GUIプログラムもグラフィカルユーザー環境で動作する必要があります。しかし、あなたはおそらくこれについてすでに考えたことがあるでしょう。
これらの理由により、OSに依存しないアプリケーションは、Javaランタイムによって提供されるような、何らかの「仮想マシン」に依存する必要があります。重要なことに、VMはOSリソース(I / O、シグナルなど)への標準インターフェースを提供します。もちろん、javaまたはpythonもIntelの命令セットの癖を処理する代わりに「バイトコード」を解釈します。しかし、それは別の話です。
OSによって機能も異なります。WindowsにはI / O完了ポートがあり、Linuxにはありません。FreeBSDにはkqueueがありますが、Linuxにはありません。Linuxにはfutexがありますが、Windowsにはありません。また、同じことを行う方法が異なります。ファイルを開くために渡すパラメーターは何ですか。彼らはどのような順番で行きますか?オペレーティングシステムの「ファイルを開く」機能を具体的にどのように呼び出しますか?
一般に、アプリケーションバイナリインターフェース(ABI)の違いにより、プログラムは互換性がありません。
プログラムはCPUで直接実行されませんか?
いや!これがオペレーティングシステムの役割であり、アプリケーションがCPUで「直接」実行されないようにします。通常、最低レベル(つまり、OS APIが構築されているレベル)では、アプリケーションはオペレーティングシステムのカーネルとインターフェイスします。
コンパイルされたプログラム自体がOS固有のライブラリを参照する必要があるためですか?
はい。多くのOSライブラリは、オペレーティングシステム自体とのインターフェースを容易にするために作成されていますが、クロスプラットフォームになるように作成されたライブラリも多数あります。これらは開発者から低レベルのOSインターフェースを隠し、そのOSのコンパイルされたバージョンが実行時に利用可能になることを前提としています(以下を参照)。
ライブラリができますが書かれたクロスプラットフォームの方法でコンパイルしたとき、彼らがすることはできません実行し、クロスプラットフォームを。オペレーティングシステム(カーネル)の特定の基盤となるコンポーネントを利用するには、特定のターゲットオペレーティングシステム用に再コンパイルする必要があります。
あるOSと別のOSでコンパイルされたプログラムの違いは何ですか?
最後に、実行可能ファイル自体には、非常に特定のバイナリ読み込みヘッダーなどが含まれていることがよくあります(たとえば、Windowsの場合はPE実行可能ファイル形式[.exe、.dllなど...] 、Linuxの場合はELF [なし、.o、.so 、など...])。これらには、特定のソフトウェアライブラリ用にコンパイルされたOS固有のバイナリをロードするコードを含めることもできます。
最後に、プログラマーの観点から:呼び出し規約。コンパイルされたコードは、特定の方法で(つまり、レジスタを介して、またはスタック上で)関数に変数を非常に特定の順序で渡します。その場合でも、誰が関数呼び出しを「クリーンアップ」する責任があるか(呼び出し元か呼び出し先か)についても合意する必要があります。標準で広く使用されているx86呼び出し規約がいくつかありますが、一部は特定のオペレーティングシステムでサポートされていない場合があります(これはABIの一部です)。