C で簡単なプログラムを作成し、Ubuntu で GCC を使用してコンパイルしました。このファイルは別のマシンで動作しますか?
- 出力バイナリの内容とその外部依存関係は?
- 他の Linux ディストリビューションで実行できますか? また、どのような状況で実行できますか?
- 他のオペレーティング システムで実行できますか?
C で簡単なプログラムを作成し、Ubuntu で GCC を使用してコンパイルしました。このファイルは別のマシンで動作しますか?
バイナリの非互換性にはいくつかのレベル/ソースがあります。
通常、「同じ OS」の異なるバージョンの別のマシンでバイナリを実行している場合 (それが何を意味するにせよ...)、正常に実行されます。完全に。問題は、コードが機能していないことではなく、コードが欠落していることです。バイナリが依存している OS の一部がターゲット マシンに存在しません。コードを実行するのではなく、実行するコードを見つけるのに失敗します (不足しているビットを使用しようとする時点までは、まったく問題ありません!)
そのため、Ubuntu gcc のバイナリは、コンパイルされたマシンよりも古い Linux システムで実行される可能性が高くなります。それは、バイナリが OS およびシステム ライブラリからどの機能に依存しているかによって異なります。
外部依存関係がないバイナリはほとんどありません。出力で使用して依存関係を調べldd
ます。問題を引き起こす可能性が最も高いのは、libgcc の依存関係です。libc とその仲間はめったに変更されないため、互換性の問題が生じることはほとんどありません。GCC は頻繁に変更されるため、バイナリが実行されるターゲット マシンが制限されます。
一般的なルールは、実行したい最も古いディストリビューションをビルド マシンとして使用することです。そのため、RHEL 2 ビルド マシンを使用すると、古いシステム以外の任意のシステムでバイナリを実行できます (いくつかの例外があります)。これは、物事をシンプルに保つための一般的なガイドラインです。多くのディストリビューション間でバイナリ互換性が必要な場合は、(C++ を使用している場合) libstdc++ に静的にリンクすることが優れた選択肢です。libgcc に静的にリンクすることは危険であり、自分が何をしようとしているのかを本当に理解していない限り、試みるべきではありません。
最後に、他の UNIX プラットフォームではライブラリの互換性がはるかに単純であることに注意してください。そのような苦痛があるのはLinuxだけです。AIX 6 (たとえば)、SunOS 5.8、HP-UX 11.00 でコンパイルされたもの、またはそれ以降のすべてのリリースで問題なく動作するもの。この環境は、古いリリースに存在するすべてのシンボルが同じセマンティクスで最新のリリースで利用できることを保証するために、システムライブラリにレガシークラフトの山を出荷できるほど十分に均一です。
それはすべて単なる機械語なので、バイナリは他の OS でも動作するはずだと思うかもしれません。彼らはしません。大きな理由はシステム コールです。カーネルから何かを呼び出す必要がある場合 (ほとんどの重要な機能に必要です)、「カーネルと対話する」方法を知っている必要があります。つまり、syscall を実行して、OS に「42 のことを実行してください」と指示します。
syscall の数は、カーネルによって異なります。そのため、Solaris バイナリは Linux からは問題ありません。
実際、一部の OS は他のカーネルのシステムコールをサポートしています。FreeBSD は Linux システムコールを認識しており、「42 を実行する」と指示すると、ELF のヘッダーのフラグをチェックし、ELF が Linux システムコールとしてスタンプされている場合は、Linux システムコール番号に対して適切なアクションを実行します。きちんとした。(もちろん、Linux ライブラリもリンクする必要があります...しかし、静的にリンクされた Linux バイナリは、外部ライブラリなしで FreeBSD で正常に動作します。)
バイナリは「単なるバイナリ」ではありません。カーネルが実行する前に解釈されるメタデータの全負荷が含まれています。バイナリの大部分は、コードとデータの塊であり、リンカ情報も含まれています。ただし、外部依存関係がないものでも、カーネルによって解析可能でなければなりません。
一部のカーネルは、PE、ELF、または a.out (廃止) などの複数のバイナリ形式を認識します。Linux バイナリは、syscall を行わなくても、Windows では決して実行されません (このようなバイナリはきれいに終了できませんが、例としては...)。これは、MS がカーネルに ELF サポートを追加しようとしていないためです。ロードおよび開始方法を説明するコードのラッパーは、Windows で読み取ることができないため、その中のコードは実行されません: Windows は実行しません。ファイルのどの部分がコードなのかわからない!
( ) ファイルはa.out
、.o
Unix ライクな OS マシンで動作します。(上記の@Nicholas WilsonによるOSの詳細)
.o
には、ファイルに記載されているすべてのライブラリが含まれています.c
。呼び出された関数のコピーがライブラリからコピーされ、.o
ファイルに指定されたコードと共にファイルに作成され.c
ます。
再度、ファイルをコンパイルし.o
て実行可能ファイルを取得します。
ファイルの使用.o
は、各部門が独自のソース ファイル ( .c
) を持ち、単一の実行可能ファイルを作成する必要がある大きなプロジェクトに取り組んでいる場合です。ファイルをコンパイルすることで取得でき.c
ます。コンパイル後、.o
ファイルを取得します。これで、これらすべての.o
ファイルを結合して 1 つの実行可能ファイルを作成できます。