Linuxは、ある意味で、相互に依存する一連の静的ライブラリと動的ライブラリです。 Linuxベースのシステムの新規ユーザーにとって、ライブラリの処理全体は謎に包まれている可能性があります。ただし、経験を積むと、オペレーティングシステムに組み込まれている大量の共有コードは、新しいアプリケーションを作成するときに有利になる可能性があります。
このトピックに触れるのに役立つように、一般的なLinuxディストリビューションで機能する最も一般的な方法を示す小さなアプリケーション例を用意しました(これらは他のシステムではテストされていません)。サンプルアプリケーションを使用してこのハンズオンチュートリアルを実行するには、コマンドプロンプトを開き、次のように入力します。
$ git clone https://github.com/hANSIc99/library_sample
$ cd library_sample/
$ make
cc -c main.c -Wall -Werror
cc -c libmy_static_a.c -o libmy_static_a.o -Wall -Werror
cc -c libmy_static_b.c -o libmy_static_b.o -Wall -Werror
ar -rsv libmy_static.a libmy_static_a.o libmy_static_b.o
ar: creating libmy_static.a
a - libmy_static_a.o
a - libmy_static_b.o
cc -c -fPIC libmy_shared.c -o libmy_shared.o
cc -shared -o libmy_shared.so libmy_shared.o
$ make clean
rm *.o
これらのコマンドを実行した後、これらのファイルをディレクトリに追加する必要があります(ls
を実行します) それらを見るために):
my_app
libmy_static.a
libmy_shared.so
アプリケーションが静的ライブラリに対してリンクすると、ライブラリのコードが結果の実行可能ファイルの一部になります。これはリンク時に1回だけ実行され、これらの静的ライブラリは通常.a
で終わります。 拡張機能。
静的ライブラリは、オブジェクトファイルのアーカイブ(ar)です。オブジェクトファイルは通常、ELF形式です。 ELFは、Executable and Linkable Formatの略で、多くのオペレーティングシステムと互換性があります。
file
の出力 コマンドは、静的ライブラリlibmy_static.a
ar
です アーカイブタイプ:
$ file libmy_static.a
libmy_static.a: current ar archive
ar -t
を使用 、このアーカイブを調べることができます。 2つのオブジェクトファイルが表示されます:
$ ar -t libmy_static.a
libmy_static_a.o
libmy_static_b.o
ar -x <archive-file>
を使用して、アーカイブのファイルを抽出できます。 。抽出されたファイルは、ELF形式のオブジェクトファイルです:
$ ar -x libmy_static.a
$ file libmy_static_a.o
libmy_static_a.o: ELF 64-bit LSB relocatable, x86-64, version 1 (SYSV), not stripped
その他のLinuxリソース
- Linuxコマンドのチートシート
- 高度なLinuxコマンドのチートシート
- 無料のオンラインコース:RHELの技術概要
- Linuxネットワーキングのチートシート
- SELinuxチートシート
- Linuxの一般的なコマンドのチートシート
- Linuxコンテナとは何ですか?
- 最新のLinux記事
ダイナミックリンクとは、共有ライブラリの使用を意味します。共有ライブラリは通常、.so
で終わります (「共有オブジェクト」の略)
共有ライブラリは、Linuxシステムへの依存関係を管理するための最も一般的な方法です。これらの共有リソースは、アプリケーションの起動前にメモリにロードされ、複数のプロセスが同じライブラリを必要とする場合、システムに1回だけロードされます。この機能により、アプリケーションによるメモリ使用量が節約されます。
もう1つの注意点は、共有ライブラリでバグが修正されると、このライブラリを参照するすべてのアプリケーションがそのバグから利益を得るということです。これは、バグが検出されないままの場合、参照している各アプリケーションがバグの影響を受けることも意味します(アプリケーションが影響を受ける部分を使用している場合)。
アプリケーションが特定のバージョンのライブラリを必要とする場合、初心者にとっては非常に難しい場合がありますが、リンカは互換性のないバージョンの場所しか知りません。この場合、リンカが正しいバージョンへのパスを見つけるのを支援する必要があります。
これは日常的な問題ではありませんが、ダイナミックリンクを理解することは確かにそのような問題を解決するのに役立ちます。
幸いなことに、このための仕組みは非常に簡単です。
アプリケーションの起動に必要なライブラリを検出するには、ldd
を使用できます。 、特定のファイルで使用される共有ライブラリを出力します:
$ ldd my_app
linux-vdso.so.1 (0x00007ffd1299c000)
libmy_shared.so => not found
libc.so.6 => /lib64/libc.so.6 (0x00007f56b869b000)
/lib64/ld-linux-x86-64.so.2 (0x00007f56b8881000)
ライブラリlibmy_shared.so
に注意してください はリポジトリの一部ですが、見つかりません。これは、アプリケーションを実行する前にすべての依存関係をメモリにロードするダイナミックリンカーが、検索する標準の場所でこのライブラリを見つけることができないためです。
リンカが互換性のないバージョンの一般的なライブラリ(bzip2
など)を検出することに関連するエラー たとえば)は、新しいユーザーにとっては非常に混乱する可能性があります。これを回避する1つの方法は、リポジトリフォルダーを環境変数LD_LIBRARY_PATH
に追加することです。 リンカに正しいバージョンを探す場所を指示します。この場合、適切なバージョンがこのフォルダーにあるため、エクスポートできます:
$ LD_LIBRARY_PATH=$(pwd):$LD_LIBRARY_PATH
$ export LD_LIBRARY_PATH
これで、ダイナミックリンカはライブラリの場所を認識し、アプリケーションを実行できるようになります。 ldd
を再実行できます ダイナミックリンカを呼び出します。ダイナミックリンカは、アプリケーションの依存関係を検査し、それらをメモリにロードします。メモリアドレスは、オブジェクトパスの後に表示されます:
$ ldd my_app
linux-vdso.so.1 (0x00007ffd385f7000)
libmy_shared.so => /home/stephan/library_sample/libmy_shared.so (0x00007f3fad401000)
libc.so.6 => /lib64/libc.so.6 (0x00007f3fad21d000)
/lib64/ld-linux-x86-64.so.2 (0x00007f3fad408000)
呼び出されたリンカーを見つけるには、file
を使用できます。 :
$ file my_app
my_app: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=26c677b771122b4c99f0fd9ee001e6c743550fa6, for GNU/Linux 3.2.0, not stripped
リンカー/lib64/ld-linux-x86–64.so.2
ld-2.30.so
へのシンボリックリンクです 、これは私のLinuxディストリビューションのデフォルトのリンカーです:
$ file /lib64/ld-linux-x86-64.so.2
/lib64/ld-linux-x86-64.so.2: symbolic link to ld-2.31.so
ldd
の出力を振り返って 、(libmy_shared.so
の横にあります)も表示されます )各依存関係が数字で終わること(例:/lib64/libc.so.6
)。共有オブジェクトの通常の命名スキームは次のとおりです。
**lib** XYZ.so **.<MAJOR>** . **<MINOR>**
私のシステムでは、libc.so.6
共有オブジェクトlibc-2.30.so
へのシンボリックリンクでもあります 同じフォルダ内:
$ file /lib64/libc.so.6
/lib64/libc.so.6: symbolic link to libc-2.31.so
ロードされたライブラリのバージョンが間違っているためにアプリケーションが起動しないという問題に直面している場合は、シンボリックリンクを調べて再配置するか、正しい検索パスを指定することで、この問題を修正できる可能性があります(「ダイナミックローダー」を参照)。 :以下のld.so ")。
詳細については、ldd
をご覧ください。 マニュアルページ。
動的読み込みとは、ライブラリ(.so
など)を意味します ファイル)は、プログラムの実行時にロードされます。これは、特定のプログラミングスキームを使用して行われます。
動的読み込みは、実行時に変更できるプラグインをアプリケーションが使用する場合に適用されます。
dlopen
を参照してください 詳細については、manページを参照してください。
ダイナミックローダー:ld.so
Linuxでは、主に共有オブジェクトを処理しているため、アプリケーションの依存関係を検出してメモリにロードするメカニズムが必要です。
ld.so
これらの場所で共有オブジェクトを次の順序で検索します:
- アプリケーションの相対パスまたは絶対パス(
-rpath
でハードコードされています GCCのコンパイラオプション) - 環境変数
LD_LIBRARY_PATH
- ファイル
/etc/ld.so.cache
システムライブラリアーカイブ/usr/lib64
にライブラリを追加することに注意してください。 管理者権限が必要です。 libmy_shared.so
をコピーできます ライブラリアーカイブに手動で移動し、LD_LIBRARY_PATH
を設定せずにアプリケーションを動作させます :
unset LD_LIBRARY_PATH
sudo cp libmy_shared.so /usr/lib64/
ldd
を実行するとき 、ライブラリアーカイブへのパスが表示されるのを確認できます:
$ ldd my_app
linux-vdso.so.1 (0x00007ffe82fab000)
libmy_shared.so => /lib64/libmy_shared.so (0x00007f0a963e0000)
libc.so.6 => /lib64/libc.so.6 (0x00007f0a96216000)
/lib64/ld-linux-x86-64.so.2 (0x00007f0a96401000)
アプリケーションで共有ライブラリを使用する場合は、コンパイル時に絶対パスまたは相対パスを指定できます。
makefileを変更し(10行目)、make -B
を呼び出してプログラムを再コンパイルします。 。次に、ldd
の出力 libmy_shared.so
を表示します 絶対パスとともにリストされます。
これを変更します:
CFLAGS =-Wall -Werror -Wl,-rpath,$(shell pwd)
これには(必ずユーザー名を編集してください):
CFLAGS =/home/stephan/library_sample/libmy_shared.so
次に再コンパイルします:
$ make
設定した絶対パスを使用していることを確認します。これは、出力の2行目に表示されます。
$ ldd my_app
linux-vdso.so.1 (0x00007ffe143ed000)
libmy_shared.so => /lib64/libmy_shared.so (0x00007fe50926d000)
/home/stephan/library_sample/libmy_shared.so (0x00007fe509268000)
libc.so.6 => /lib64/libc.so.6 (0x00007fe50909e000)
/lib64/ld-linux-x86-64.so.2 (0x00007fe50928e000)
これは良い例ですが、他の人が使用できるライブラリを作成している場合、これはどのように機能しますか?新しいライブラリの場所は、/etc/ld.so.conf
に書き込むことで登録できます。 または<library-name>.conf
を作成します /etc/ld.so.conf.d/
の下の場所を含むファイル 。その後、ldconfig
ld.so.cache
を書き換えるには実行する必要があります ファイル。この手順は、特別な共有ライブラリを提供するプログラムをインストールした後に必要になる場合があります。
ld.so
をご覧ください 詳細については、マニュアルページをご覧ください。
通常、32ビットバージョンと64ビットバージョンのアプリケーションには異なるライブラリがあります。次のリストは、さまざまなLinuxディストリビューションの標準的な場所を示しています。
RedHatファミリー
- 32ビット:
/usr/lib
- 64ビット:
/usr/lib64
Debianファミリー
- 32ビット:
/usr/lib/i386-linux-gnu
- 64ビット:
/usr/lib/x86_64-linux-gnu
ArchLinuxファミリー
- 32ビット:
/usr/lib32
- 64ビット:
/usr/lib64
FreeBSD (Linuxディストリビューションではなく技術)
- 32ビット:
/usr/lib32
- 64ビット:
/usr/lib
これらの主要なライブラリを探す場所を知っていると、壊れたライブラリリンクが過去の問題になる可能性があります。
最初は混乱するかもしれませんが、Linuxライブラリの依存関係管理を理解することは、オペレーティングシステムを制御していると感じる方法です。他のアプリケーションでこれらの手順を実行して、一般的なライブラリに精通し、途中で発生する可能性のあるライブラリの課題を修正する方法を引き続き学習してください。