linux共有ライブラリの件


ほとんどの大規模なソフトウェアプロジェクトにはいくつかのコンポーネントが含まれています.後で他のプロジェクトで一部のコンポーネントを発見したり、組織目的で分離したりすることがあります.再利用可能または論理的に異なる関数のセットがある場合は、ソースコードを現在のプロジェクトにコピーして常に再コンパイルする必要がないように、soライブラリを構築すると役立ちます.これにより、異なるモジュールのプログラムを交差させずに、他のプログラムに影響を与えることなく、その1つだけを変更できます.作成してテストすると、プロジェクトに構築するたびに時間と手間を省くために、何度も安全に繰り返し使用できます.
静的ライブラリの構築は非常に簡単で、それらに関する問題は少ないので、私はそれらを紹介しません.共有ライブラリについて説明します.これは多くの人にとってもっと困惑しているようです. 
説明で使用するコードの例:
 foo.hファイル:

#ifndef foo_h__
#define foo_h__

extern void foo(void);

#endif  // foo_h__

foo.cファイル
#include 


void foo(void)
{
    puts("Hello, I am a shared library");
}

  main.cファイル
#include 
#include "foo.h"

int main(void)
{
    puts("This is a shared library test...");
    foo();
    return 0;
}

foo.hファイルは私たちのライブラリの個別の関数インタフェースfoo(),fooを定義した.cファイルにはインタフェース関数の実装、mainが含まれている.cはライブラリファイルを使用したプログラムコードです
ステップ1-picを使用してコンパイル
ライブラリのソースコードを場所に関係のないコードにコンパイルする必要があります.
$ gcc -c -Wall -Werror -fpic foo.c

ステップ2ターゲットファイルから共有ライブラリを作成する
gcc -shared -o libfoo.so foo.o

ステップ3共有ライブラリのリンク
ご覧のように、これは実際には簡単です.共有ライブラリがあります.mainをコンパイルしましょう.cはlibfooにリンクし、最終的にコンパイルされたプログラムはtestと命名されています.-lfooオプションはfooを検索しているわけではありません.o、libfooです.so. GCCは、すべてのライブラリがlibで始まると仮定し、.soまたは.a末尾(.soは共有ライブラリまたは共有ライブラリに使用され、.aは静的リンクライブラリに使用される).
$ gcc -Wall -o test main.c -lfoo
/usr/bin/ld: cannot find -lfoo
collect2: ld returned 1 exit status

ああ!リンクはibfooをどこで探しているのか分かりませんが、GCCはデフォルトで一連の場所を探していますが、私たちのディレクトリはこの場所リストにありません.-Lオプションを使用してgccにlibfooライブラリを探しに行くように伝える必要があります.この列では現在のパスを使用します.
$ gcc -L/home/username/foo -Wall -o test main.c -lfoo

手順4ライブラリを実行中に使用可能にする
コンパイルしたtestファイルを実行すると
$ ./test
./test: error while loading shared libraries: libfoo.so: cannot open shared object file: No such file or directory

ローダは共有ライブラリを見つけることができません(注釈3)標準的な場所にインストールしたことがありませんので、ローダを助ける必要があります.環境変数LDを使用することができます.LIBRARY_PATHまたはrpath.まずLDを使ってみましょうLIBRARY_PATH
LD_の使用LIBRARY_PATH
共有ライブラリのパスをLD_に追加しましょうLIBRARY_PATH中
$ export LD_LIBRARY_PATH=/home/username/foo:$LD_LIBRARY_PATH
$ ./test
This is a shared library test...
Hello, I am a shared library

testは実行できますLD_LIBRARY_PATHは迅速なテストや管理者権限のないシステムに適していますが、不利な面はLD_をエクスポートすることです.LIBRARY_PATH変数は、LD_に依存して実行する他のプログラムに問題が発生する可能性があることを意味します.LIBRARY_PATH、以前の状態に戻らない場合.
rpathの使用
rpathを試してみましょう(まずLD_LIBRARY_PATHをクリアします).Rpathまたは実行パスは、デフォルトの場所または環境変数に依存するのではなく、共有ライブラリの場所を実行可能ファイルに埋め込む方法です.リンクフェーズでこの操作を行います.-Wl,-rpath=/home/username/fooオプションに注意してください.-Wlセクションでは、カンマで区切られたオプションがリンクに送信されるので、-rpathに作業ディレクトリオプションを追加してリンクに送信します.
$ unset LD_LIBRARY_PATH
$ gcc -L/home/username/foo -Wl,-rpath=/home/username/foo -Wall -o test main.c -lfoo
$ ./test
This is a shared library test...
Hello, I am a shared library

プログラムごとに共有ライブラリの場所を独立してリストできるので、rpathの方法も素晴らしいです.
rpath vs. LD_LIBRARY_PATH
しかし、rpathにはいくつかの欠点がある.まず、プログラムのすべてのユーザーがそれらの場所のライブラリにアクセスできるように、共有ライブラリを固定された場所にインストールする必要があります.これは、システム構成の柔軟性が低下することを意味します.次に、ライブラリがNFSマウントまたは他のネットワークドライブを参照している場合、プログラムの起動時に望ましくない遅延が発生する可能性があります.
ldconfigコマンドを使用してldを変更します.so
システム上の誰もがこのライブラリを使用できるように、ライブラリをインストールしたい場合はどうすればいいですか?このためには、管理者権限が必要です.2つの理由で、まず、ライブラリを標準の場所に配置する必要があります.通常のユーザーは書き込みアクセス権がありません./usr/libまたは/usr/local/libです.次にldを変更する必要があります.soプロファイルとキャッシュ.rootユーザーとして次の操作を行います.
$ cp /home/username/foo/libfoo.so /usr/lib
$ chmod 0755 /usr/lib/libfoo.so

これで、ファイルは標準の場所にあり、正しい権限を持っており、誰もが読み取ることができます.ローダが使用できることを伝える必要がありますので、キャッシュを更新しましょう.
$ ldconfig

これにより、共有ライブラリへのリンクが作成され、すぐに使用できるようにキャッシュが更新されます.よくチェックしてみましょう.
$ ldconfig -p | grep foo
libfoo.so (libc6) => /usr/lib/libfoo.so

ライブラリがインストールされました.テストの前に、LDを再度クリアする必要があります.LIBRARY_PATH、念のため:
$ unset LD_LIBRARY_PATH

実行可能ファイルを再リンクします.ライブラリはデフォルトの場所に格納されており、rpathオプションは使用されていないため、-Lオプションは必要ありません.
$ gcc -Wall -o test main.c -lfoo

ldd使用ライブラリの/usr/libを使用することを確認します.
$ ldd test | grep foo
libfoo.so => /usr/lib/libfoo.so (0x00a42000)

いいですね.それを実行してみましょう.
$ ./test
This is a shared library test...
Hello, I am a shared library

共有ライブラリの構築方法、リンク方法、共有ライブラリで最も一般的なローダの問題を解決する方法、および異なる方法のプラスとマイナスの影響について説明しました.
共有ライブラリのロード順序をまとめます.
1実行可能ファイルのDT_RPATH(-Wl,--rpath=)セクションでは、ここにDT_がない限り検索されます.RUNPATH(-Wl,--rpath=.,--enable-new-dtags)節
2 LD_LIBRARY_PATHで検索します.セキュリティ上の理由で実行可能ファイルをsetuid/setgidに設定した場合、この手順はスキップされます.
3実行可能ファイルのDT_RUNPATHでは、setuid/setgidビットが設定されていない限り検索します(セキュリティ上の理由).
4キャッシュファイル/etc/ld/so/cacheで検索します(-z nodeflibリンクオプションを使用して無効にできます).
5デフォルトの/libおよび/usr/libで検索-z nodeflibリンクオプションを使用して無効にできます).