共有 object( .so
) ファイルと object( .o
) ファイルの関係は?
例を挙げて説明していただけますか?
共有 object( .so
) ファイルと object( .o
) ファイルの関係は?
例を挙げて説明していただけますか?
次の C ソース ファイルがあるとします。name.c
#include <stdio.h>
#include <stdlib.h>
void print_name(const char * name)
{
printf("My name is %s\n", name);
}
コンパイルすると、cc name.c
が生成されname.o
ます。.o には、name.c で定義されたすべての関数と変数のコンパイル済みコードとデータ、およびそれらの名前と実際のコードを関連付けたインデックスが含まれています。nm
ツール (Linux および他の多くの Unix で利用可能) を使用してそのインデックスを調べると、次の 2 つのエントリに気付くでしょう。
00000000 T print_name
U printf
これが意味すること: .o. には 2 つのシンボル (関数または変数の名前であり、クラス、構造体、または型の名前ではない) が格納されています。でマークされた最初のものには、T
実際にはその定義がに含まれていますname.o
。もう一方の でマークされてU
いるものは、単なる参照です。のコードはprint_name
ここにありますが、のコードは見つかりprintf
ません。実際のプログラムを実行すると、完全なプログラムまたは完全なライブラリにリンクするために、参照であるすべてのシンボルを見つけ、他のオブジェクト ファイルでそれらの定義を検索する必要があります。したがって、オブジェクト ファイルは、ソース ファイルで検出された定義であり、バイナリ形式に変換され、完全なプログラムに配置するために使用できます。
.o ファイルを 1 つずつリンクすることはできますが、リンクすることはできません。通常、それらは多数あり、それらは実装の詳細です。それらをすべて、よく知られている名前を付けて、関連するオブジェクトのバンドルにまとめたいと思うでしょう。これらのバンドルはライブラリと呼ばれ、静的と動的の 2 つの形式があります。
静的ライブラリ(Unixの場合) には、ほとんどの場合、( C コア ライブラリである、C 数学ライブラリであるなどの.a
例が含まれます) などの接尾辞が付いています。で静的ライブラリを構築する例を続けます。実行すると、次のように表示されます。libc.a
libm.a
ar rc libname.a name.o
nm
libname.a
name.o:
00000000 T print_name
U printf
ご覧のとおり、これは主にオブジェクト ファイルの大きなテーブルであり、その中のすべての名前を検索するインデックスが付いています。オブジェクト ファイルと同様に、every.o
で定義されたシンボルとそれらによって参照されるシンボルの両方が含まれます。別の.o (たとえばdate.o
へ)にリンクするとprint_date
、上記のような別のエントリが表示されます。
静的ライブラリを実行可能ファイルにリンクすると、ライブラリ全体が実行可能ファイルに埋め込まれます。.o
これは、すべての個々のファイルをリンクするのと同じです。ご想像のとおり、これによりプログラムが非常に大きくなる可能性があります。特に (ほとんどの最新のアプリケーションがそうであるように) 多くのライブラリを使用している場合はそうです。
動的ライブラリまたは共有ライブラリには、接尾辞が付きます。これは、静的な類似物と同様に、コンパイルされたすべてのコードを参照するオブジェクト ファイルの大きなテーブルです。でビルドします。ただし、 with を見ると、静的ライブラリとはかなり異なります。私のシステムでは、約2ダースの記号が含まれており、そのうちの2つだけがandです。.so
cc -shared libname.so name.o
nm
print_name
printf
00001498 a _DYNAMIC
00001574 a _GLOBAL_OFFSET_TABLE_
w _Jv_RegisterClasses
00001488 d __CTOR_END__
00001484 d __CTOR_LIST__
00001490 d __DTOR_END__
0000148c d __DTOR_LIST__
00000480 r __FRAME_END__
00001494 d __JCR_END__
00001494 d __JCR_LIST__
00001590 A __bss_start
w __cxa_finalize@@GLIBC_2.1.3
00000420 t __do_global_ctors_aux
00000360 t __do_global_dtors_aux
00001588 d __dso_handle
w __gmon_start__
000003f7 t __i686.get_pc_thunk.bx
00001590 A _edata
00001594 A _end
00000454 T _fini
000002f8 T _init
00001590 b completed.5843
000003c0 t frame_dummy
0000158c d p.5841
000003fc T print_name
U printf@@GLIBC_2.0
共有ライブラリは、1 つの非常に重要な点で静的ライブラリと異なります。それは、最終的な実行可能ファイルに自分自身を埋め込まないことです。代わりに、実行可能ファイルには、リンク時ではなく実行時に解決される共有ライブラリへの参照が含まれています。これには多くの利点があります。
いくつかの欠点があります。
(考えてみれば、これらの多くは、プログラムがクラスのオブジェクトを他のオブジェクトに直接埋め込む代わりに、参照やポインターを使用する、または使用しない理由です。類推は非常に直接的です。)
わかりました、それは多くの詳細であり、リンクプロセスが実際にどのように機能するかなど、多くをスキップしました. フォローしていただけると幸いです。そうでない場合は、説明を求めてください。