1.動的ライブラリと静的ライブラリの基本概念
1.ダイナミックライブラリ: Linuxでは、ダイナミックライブラリは.soという接尾辞が付いたファイルです。ダイナミックライブラリは、プログラムのコンパイル時にオブジェクトコードにリンクされませんが、プログラムの実行時にロードされます。異なるアプリケーションが同じライブラリを呼び出す場合、メモリ内には共有ライブラリのインスタンスが1つしかないため、スペースを浪費する問題が回避されます。ダイナミックライブラリは、プログラムの実行中にのみロードされます。これにより、静的ライブラリがプログラムの更新、展開、およびリリースページにもたらす問題も解決されます。ユーザーは、ダイナミックライブラリの増分更新のみを更新する必要があります。
2.静的ライブラリ: Linuxでは、静的ライブラリはサフィックスが.aのファイルです。プログラムがコンパイルおよびリンクされると、ライブラリ内のコードのコピーが実行可能プログラムに配置されます。
3.静的リンク:ライブラリ内のコードを実行可能プログラムにコピーするプロセス。
4.ダイナミックリンク:実行可能ファイルの実行が開始される前に、外部関数のマシンコードがオペレーティングシステムによってディスク上のダイナミックライブラリからメモリにコピーされます。このプロセスはダイナミックリンクと呼ばれます。
5.ライブラリ名の認識:例:libc.so、プレフィックスlibとサフィックス.soを削除するだけです
6.リンクの本質: .libファイルと.oファイル
2.動的ライブラリと静的ライブラリの長所と短所
以下では、動的リンクと静的リンクを使用して実行可能プログラムをそれぞれ生成します(静的リンクにgccを使用する場合は-staticが必要であることに注意してください)。
1.動的リンク:
最初にMakefileを作成します。
1 mytest:test.c 2 gcc -o $@ $^ 3 .PHONY:clean 4 clean: 5 rm -f mytest ~
対応するtest.cコード:
1 #include<stdio.h> 2 int main() 3 { 4 printf("hello ksy\n"); 5 return 0; 6 }
2.静的リンク:
対応するMakefile:
mytest_static:test.c 2 gcc -o $@ $^ -static 3 .PHONY:clean 4 clean: 5 rm -f mytest
test.cコードは、ダイナミックリンクと同じです。
コマンドの実行中にエラーが報告された場合は、次の2つのコマンドを実行できます。
1.1。
sudo yum install glibc-static
2.2。
sudo yum install glibc-static libstdc++-static
以下では、これら2つの方法で生成された実行可能ファイルのサイズを確認できます。
静的リンクによって生成される実行可能プログラムファイルのサイズは、動的リンクの約100倍であることがわかります。はるかに大きいです
同様に、fileコマンドを使用して、mytest、mytest_staticのファイル属性を表示できます。
lddを使用して、レイジーに応じて実行可能プログラムのライブラリを表示します(動的リンクによって生成された実行可能プログラムには依存ライブラリのみがあり、静的リンクによって生成された実行可能プログラムには依存ライブラリがなく、静的リンクはライブラリファイルのコードを実行可能プログラムに追加します。実行可能ファイル内。
最後に要約すると:
静的ライブラリの利点:
1)プログラムを公開する場合、ライブラリは実行可能ファイルにパッケージ化されているため、対応するライブラリを提供する必要はありません。
2)ライブラリが実行可能ファイルにパッケージ化されているため、ライブラリのロード速度が速くなります。
静的ライブラリのデメリット:1)ライブラリはアプリケーション(最終的な実行可能ファイル)にパッケージ化されます。ライブラリが多数ある場合、アプリケーションは非常に大きくなります。
2)ライブラリが変更されたため、プログラムを再コンパイルする必要があります。ソースコードが多い場合は、再コンパイルに1日かかる場合があります。1.ダイナミックライブラリの利点
1)実行可能プログラムのサイズが小さい:プログラムは実行時にダイナミックライブラリをロードし、実行可能プログラムと一緒にパッケージ化されません
2)ダイナミックライブラリが更新され、プログラムを再コンパイルする必要はありません(絶対ではありません) 、関数のインターフェイスが変更されていない場合、コンテンツは問題ありません)
2.ダイナミックライブラリの欠点プログラムがリリースされたら、ダイナミックライブラリをユーザーに提供する必要があります。
ダイナミックライブラリはアプリケーションにパッケージ化されておらず、読み込み速度は比較的遅いです。
3.静的ライブラリのパッケージ化と使用
1.まず、コンパイルプロセスを思い出してみましょう。gccコンパイルは大きく4つのプロセスに分けることができます。
- gccプリプロセッサ:
.c文件
コンパイル预处理
済み.i文件
- gccコンパイラ:アセンブリファイル
预处理
に.i文件
コンパイル.s
- gccアセンブラ:
.s
コンパイル汇编文件
済み.o
二进制文件
- gccリンカー:実行可能ファイルへ
.o
のリンク二进制文件
4つのステージに対応するコマンドは次のとおりです。hello.cの例を次に示します。
- 前処理:
gcc -E hello.c -o hello.i
- コンパイル:
gcc -S hello.i -o hello.s
- コンパイル:
gcc -c hello.s -o hello.o
- リンク:
gcc hello.o -o hello
4つの段階に対応する機能:
前処理:(1).cファイルのヘッダーファイルを展開し、.i前処理ファイルの先頭に追加します;(2)次に、.cファイルコードを.iヘッダーファイルのコンテンツに追加します;(3)マクロを定義する値の大きさが特定の値に置き換えられ、元のコードのコメントが削除されます。
コンパイル:cファイルのアセンブリファイルへの変換は、2つのプログラム構文の変換です。
アセンブリ:アセンブリファイルをバイナリファイルにプログラムします。現時点では、ファイルの特定の内容を確認できません。
リンク:関数ライブラリ内の対応するコードをオブジェクトファイルに結合します。
2.静的ライブラリのパッケージ化
静的ライブラリのパッケージ化の本質は、.oに書き込んだコードをコンパイルして、後続のプロセスを実行せずにバイナリファイルを形成し、形成されたファイルをパッケージ化することです。製造プロセスは次のとおりです。
まず、静的ライブラリの作成
1.命名規則
1)lib+ライブラリの名前+.a
2)例:libmyMath.a
2.製造ステップ:1)対応する.oバイナリファイル.c-> .oを生成します。例:gcc sum.c -c sum.o
2)ar rcs +静的ライブラリの名前(libMytest.a)を使用して、生成された.oファイルをパッケージ化します。 +すべての.oを生成
3)静的ライブラリを公開して使用する:
1。静的ライブラリを公開する
2.ヘッダーファイル
説明:.cファイル、つまりソースコードを.oバイナリファイルに変換した後、顧客はコアテクノロジがどのように実装されているかを知ることができません。
arは.oバイナリファイルをパッケージ化することであり、rcはパッケージ化パラメータであり、すべての.oバイナリファイルは.aファイル(静的ライブラリ)にパッケージ化されます。つまり、静的ライブラリはパッケージ化されたバイナリのコレクションです。インターフェイスAPIはヘッダーファイルに反映されます。
以下は、静的ライブラリの次のパッケージを示す小さな例です。このプロセスを示すために、mypow.c、myadd.c、mypow.h、myadd.hを作成しました。
これらのファイルの内容を次に示します。
myadd.h
1 #ifndef __MYADD_H__ 2 #define __MYADD_H__ 3 int add(int x,int y); 4 #endif
myadd.c
1 #include"myadd.h" 2 int myadd(int x,int y) 3 { 4 return x+y; 5 } ~
mypow.h
1 #ifndef __MYPOW_H__ 2 #define __MYPOW_H__ 3 int mypow(int x,int y); 4 #endif ~
mypow.c
1 #include"mypow.h" W> 2 int mypow(int x,int y) 3 { W> 4 if(y==0) 5 return 1; 6 if(y==1) 7 return x; 8 9 return x*mypow(x,y-1); 10 }
静的ライブラリを生成するための手順を紹介しましょう。
arツールは、形成された.oファイルをパックします(パック時に-rcオプションを使用)。ここで、rとcはそれぞれreplaceとcreatです。ここでは、ライブラリ名をmyMathに設定します。
以下にMakefileを記述します。
1 libmyMath.a:myadd.o mypow.o 2 ar -rc $@ $^ 3 myadd.o:myadd.c 4 gcc -c $< 5 mypow.o:mypow.c 6 gcc -c $< 7 #清除 8 .PHONY:clean 9 clean: 10 rm -rf output *.o *.a 11 #发表 12 .PHONY:output 13 output: 14 mkdir -p mylib/include 15 mkdir -p mylib/lib 16 cp *.h mylib/include 17 cp *.a mylib/lib ~ ~
説明:
- インクルードフォルダ:ユーザーが呼び出すために提供されるヘッダーファイルを保存します
接口API
- libフォルダー:ライブラリファイルを保存します。つまり、生成された静的ライブラリ、動的ライブラリ
- srcフォルダー:ソースファイルを保存します
- test.cプログラム:ユーザーは
head.h头文件
内部のインターフェイスを呼び出してから、静的ライブラリに実装するアルゴリズムを呼び出します(ただし、これはソースコードではなく、バイナリファイルにコンパイルされます)
以下では、それぞれmakeとmakeoutを実行します。リリースのために作ります。
これでパッケージ化に成功しました。これで、他の人に使用してもらうことができます。
このパッケージ化された静的ライブラリをテスト用のディレクトリに配置しましょう。
対応するテストtest.cの内容:
1 #include<stdio.h> E> 2 #include"mypow.h" 3 int main() 4 { E> 5 printf("%d\n",mypow(2,5)); 6 7 }
対応するmakefile:
1 mytest:test.c 2 gcc -o $@ $^ 3 .PHONY:clean 4 clean: 5 rm -f mytest
何が悪かったのかがわかりました。gccを使用して静的リンクを使用する場合、ライブラリファイルのパス、ヘッダーファイルのパス、およびリンクするライブラリをコンパイラに通知する必要があります。これら3つの操作に対応するオプションは次のとおりです。
パラメータの説明:
-I
パラメーター:ヘッダーが配置されているフォルダーの名前を指定します。フォルダー名はパラメーターと一緒に書き込むことができます。-L
パラメータ:静的ライブラリのフォルダ名を指定します-l
パラメーター:静的ライブラリーの名前を指定しますが、名前は次のようにする必要があります。例:パラメーター値を指定する場合掐头去尾
、元の静的ライブラリー名は、です。libmyMath.a
-l
-l myMath
Makefileを変更してみましょう
1 path =$(shell pwd) 2 3 mytest:test.c 4 gcc -o $@ $^ -I $(path)/mylib/include -L $(path)/mylib/lib -l myMath -static 5 .PHONY:clean 6 clean: 7 rm -f mytest ~
ここでは、pathを使用して、絶対パスを使用してパスを取得します。
次に、プログラムをコンパイルして実行します。
4つのダイナミックライブラリのパッケージ化と使用
1.ダイナミックライブラリの説明
1.命名規則:
1)lib + name + .so
2)例:libmyMath.so
2.製造ステップ:1)位置に依存しないコードを生成する(位置に依存しない.oを生成する)
2).oを共有ライブラリ(ダイナミックライブラリ)にパッケージ化する
3)共有ライブラリを公開して使用する:
注:静的ライブラリによって生成される.oファイルは同じです場所としてgccを使用して位置に依存しない.oファイルを生成するには、パラメーター-fPIC(一般的に使用される)または-fpicを使用する必要があります。
2.ダイナミックライブラリの作成例
場所に依存しない.oファイルを生成することの意味を理解するには、前に学習した仮想アドレス空間に連絡する必要があります。
Linuxで1つ
运行的程序
( )を開くと、オペレーティングシステムは静的ライブラリによって生成された仮想アドレス空間からではなく进程
1つ(32ビットオペレーティングシステムの場合)0-4G的地址空间
(虚拟地址空间
)を割り当て、生成されたバイナリファイルが配置されます。使用されているために生成されます。ダイナミックライブラリによって生成されたダイナミックライブラリ/共有ライブラリは、プログラムのパッケージ化時にプログラムにパッケージ化されません。これが実行されるだけで、ダイナミックライブラリがプログラムにロードされます。つまり、のスペースにロードされます。上の図ですが、毎回スペースにロードされます。または、上記の静的ライブラリと同じディレクトリ構造を作成します。虚拟地址空间
内存中。
位置有关
二进制文件(.o文件)
0开始
(.o文件)
代码段
.text代码区
.o代码每次都被放到同一个位置
绝对地址
位置无关
二进制文件(.o文件)
.o文件
可执行文件
一个记录
程序运行之后
共享库
共享库
位置可能不同
同様に、上記のヘッダーファイルを再利用に使用します。Makfileを見てみましょう。
1 libmyMath.so:myadd.o mypow.o 2 gcc -shared -o $@ $^ 3 myadd.o:myadd.c 4 gcc -fPIC -c $< 5 mypow.o:mypow.c 6 gcc -fPIC -c $< 7 #清除 8 .PHONY:clean 9 clean: 10 rm -rf output *.o *.so 11 #发表 12 .PHONY:output 13 output: 14 mkdir -p mylib/include 15 mkdir -p mylib/lib 16 cp *.h mylib/include 17 cp *.so mylib/lib
パラメータの説明:
1.-PIC:場所に依存しない.oファイルを生成します2.-
共有:共有、つまり.oファイルをダイナミックライブラリ/共有ライブラリにパッケージ化します
3.ダイナミックライブラリの作成が上記で完了し、その後、次の2つファイルは、ファイルがユーザーに公開された後に呼び出すことができます4.include / head.h:インターフェースAPIを定義するヘッダーファイル
5.lib/libmyMath.so:コンパイルされたソースコードバイナリファイルをカプセル化する動的ライブラリ
同様に、mylibをテスト用のテストファイルの下に置きます。
ただし、これは動的リンクであるため、パスがどこにあるかをコンパイラに通知するだけでなく、パスがどこにあるかをシステムに通知する必要があります。したがって、環境変数LD_LIBRARY_PATHをインポートする必要があります。
LD_LIBRARY_PATH = / home / ksy / BK / Test / mylib /lib/をエクスポートします。その後、次を使用できます。