コンピュータシステム:プログラマの視点(3ed)p733 言う
7.9 実行可能ターゲットファイルのロード
実行可能オブジェクトファイルprogを実行するには、Linuxシェルのコマンドラインにその名前を入力します。
Linux> ./prog
prog
組み込みのシェルコマンドと一致しないため、シェルはprog
実行可能オブジェクトファイルであると仮定します。このファイルは、次のメモリ常駐オペレーティングシステムコードを呼び出して生成されます。荷物を載せる人。すべてのLinuxプログラムはこの関数を呼び出してローダーを呼び出すことができます。execve
これについてはセクション8.4.6で詳しく説明します。
p736から:動的接続中
7.10 共有ライブラリとのダイナミックリンク
ライブラリを作成したら、図7.7のサンプルプログラムにリンクします。
linux> gcc -o prog2l main2.c ./libvector.so
prog2l
これにより、実行時にリンクできる形式で実行可能なオブジェクトファイルが生成されます。libvector.so
基本的なアイデアは、実行可能ファイルが作成されたときにいくつかのリンクを静的に実行し、プログラムがロードされたときにリンクプロセスを動的に完了することです。実現することが重要ですlibVector.soのコードやデータのどれも実際に実行可能ファイルにコピーされません。prog2l
この時点で。代わりに、リンカーは、いくつかの再配置およびシンボルテーブル情報をコピーします。libvector.so
これにより、ロード時にコードとデータへの参照を確認できます。ローダーが実行可能ファイルをロードして実行すると、
prog2l
セクション7.9で説明されている技術を使用して部分的にリンクされた実行可能ファイルをロードします。prog2l
次に、それ自体が共有オブジェクトである動的リンカーのパス名を含むセクションが含まれているprog2l
ことを確認します.interp
(たとえば、ld-linux.so
Linuxシステムなど)。ローダーは通常どおりアプリケーションに制御を渡すのではなく、動的リンカーをロードして実行します。 動的リンカーその後、完了ジョブの接続次の再配置を実行して:
- テキストとデータを
libc.so
メモリセグメントに再配置する- テキストとデータを
libvector.so
異なるメモリセグメントに再配置するprog2l
およびで定義されたシンボルへの参照を再配置します。libc.so
libvector.so
上記の動的リンク状況は、「静的ロード、動的リンク」状況です。Steven Kitの答え:
静的ロード、動的接続:リンカー/usr/bin/ld を再利用しますが、共有ライブラリ (.so) を使用します。荷物を載せる人64ビットx86ベースのDebian 9の/lib64/ld-linux-x86-64.so.2(現在は/lib/x86_64-linux-gnu/ld-2.24.soにマップされています)などのバイナリ用インタプリタです。主要な実行可能ファイルもロードするカーネルによって。
違いは、CSAPPではローダーが(後ろにあるカーネルコード)、execve()
リンカーはld-linux.so
(コンパイル時にリンクは発生しませんが、ld
実際のリンクはロード時に発生しますld-linux.so
)と言うようです。
リンカーとは何ですか、動的リンキングのローダーは何ですか?
ありがとうございます。
答え1
強調する重要な点は次のとおりです。
動的リンカーその後、完了ジョブの接続
重要な言葉を逃した」終わる」。リンカーはld
接続タスクを開始し、ビルド時にできるだけ多くのタスクを実行し、それを完了するために必要なデータ構造を準備します。
その後、ローダーはプログラムと必要なライブラリーをロードする接続操作(記号の一致と必要な再配置の実行)を完了できます。
CSAPPの用語では、動的ローダーはカーネルのELFローダーであり、動的リンカーはld-linux.so
。
GNU Cライブラリの独自のドキュメントld.so
は次のとおりです。動的リンカー/ローダー。ld.so
(またはld-linux.so
)それ自体はリンクだけでなくロードも多く行うので、両方の用語を適用することは正確です。カーネルは実行可能ファイル自体とそのインタプリタ(ダイナミックリンカ/ローダ)をロードし、インタプリタは必要な他のすべてをロードします。図書館。
バラよりプログラムの実行方法:ELFバイナリこれらすべてがLinuxシステムでどのように機能するかを学びます。
答え2
動的リンカーはcallですld.so
。以下で設定を見つけることができます/etc/ld.so*
。ほとんどの設定は.soを検索するパスに関連しています。
ld
実行可能ファイルの接続を完了する前に、すべての機能が共有ライブラリにあることを確認する必要があります(まあ...技術的には実行する必要はありませんが、それを実行します。つまり、Fromで起動する場合)、コンピュータごとに.soが異なる可能性があります。新機能があるかもしれませんが、以前の機能は失われ、バイナリは実行されません。
リンカ()は、共有ライブラリが必要なバイナリを生成すると、セクションに特定の数のld
シンボルとそのアドレスを予約します。.text
これは、動的リンカー(ld.so
)が実行時に接続を完了するために使用することです。対応する.soファイルからシンボルを検索し、必要なときはいつでもそのアドレスを保存します(関数の場合は通常コマンドリストなので、jump
各関数を一度だけリンクできます)。
もちろんバイナリを削除すると特殊記号削除しないでください。
ロードされるライブラリのリストを表示するには、ldd
実行可能ファイルに対して実行できます。特に、シンボル(フルパス)を確認するためにどの.soが選択されているかを示します。環境変数を使用して検索パスを変更できますLD_LIBRARY_PATH
。これにより、他のファイルまたは削除された.soファイルに対してテストできます(cmake、automakeも--rpath
そのファイルを使用します。同じで、パスはバイナリに直接保存されます)。
正確にどの部分がファイルをロードして実行しているのかわかりません。execve()
これらすべてのロジックは直接実装されていない可能性があります。しかし、実行ファイルの実行方法を知っている最も低いレベルの関数にはかなり近いです。
実際、動的接続はとても簡単です標準リンカーと比較したプロセス:
- ロード.so
- .soでシンボルを検索する
- シンボルアドレスを保存
完璧。だからこそ早すぎます。
メモ:use を使うとさらにダイナミクスが得られますが、dlopen()
その部分を言うようにはなりません。