Linux学習記録 - 基礎IO (3)


1. 動的ライブラリと静的ライブラリを理解する

1. システムは、言語のヘッダー ファイルとライブラリ ファイルをプリインストールします。ヘッダー ファイルはメソッドの説明を提供し、ライブラリはメソッドの実装を提供します。ヘッダーとライブラリの間には対応関係があり、これらを組み合わせて使用​​する必要があります。 2. ヘッダー ファイルは前処理
段階で導入されます。はい、リンクの本質は実際にはリンク ライブラリです。
3. vs2019 などの開発環境のインストールは、基本的に言語をサポートするライブラリとヘッダー ファイル、およびコンパイラ ソフトウェアをインストールすることです。 。
4. ヘッダー ファイルには文法リマインダー機能があり、コンパイラはユーザーがヘッダー ファイルに入力した内容を継続的に検索する必要があります。リマインダー機能はヘッダー ファイルに依存します。
5. 環境は、コードのどこに問題があるかを認識します。コンパイラには、構文チェックのためのコマンド ライン モードとその他の自動モードがあります。内部的には、オペレーターがコードを記述すると、コンパイラーはリンクではなく前処理、コンパイルを続行します。エラーがある場合は、コンパイル段階で報告されます。

2. 動的ライブラリと静的ライブラリがあるのはなぜですか?

開発効率を向上させるため。

これにより、オペレーターがコードを実装する時間が節約され、各関数を自分で記述する必要がなくなりました。

3. 簡易実装ライブラリ

1. 静的ライブラリ

静的ライブラリのサフィックスは .a で、ダイナミック ライブラリのサフィックスは .so です。Windows では、静的ファイルは .lib で、動的ファイルは .dll です。

libstdc++.so.6 libc-2.17.so などのライブラリの名前には lib という接頭辞が付いており、実際の名前は接頭辞と接尾辞を削除する必要があるため、stdc++、c-2.17 になります。

一般的なクラウドサービスの場合、デフォルトでは動的ライブラリのみが存在し、静的ライブラリは存在しないため、別途静的ライブラリをインストールする必要があります。

これにより、加算、減算、乗算、除算のライブラリが作成されます。

加算: myadd.c および .h 減算: mysub.c および .h

#include <stdio.h>
#include "myadd.h"
#include "mysub.h"

int main()
{
    
    
    int x = 7;
    int y = 4;
    printf("%d + %d = %d\n", x, y, Add(x, y));
    printf("%d - %d = %d\n", x, y, Sub(x, y));
    return 0;
}

ここに画像の説明を挿入

ただし、この方法ではソース コードが直接ユーザーに渡されるのですが、実際にはそうではなく、ライブラリとしてパッケージ化されます。

mylib と otherperson という 2 つのディレクトリを作成し、mylib は定義したライブラリであり、書き込まれたヘッダー ファイルをライブラリに移動します。

ここに画像の説明を挿入

ライブラリにパッケージ化する方法はわかりませんが、.o ファイルにすることはできます。これはリンク段階前のファイルです。ライブラリはプログラムがリンクされるときにインポートされるので、インクルードできます。図書館で。ライブラリ内のソース コードは、.o ファイルと .h ファイル形式です。

ここに画像の説明を挿入

ユーザーのディレクトリにはヘッダー ファイルと .o ファイルがあり、これらのファイルを使用するメイン プログラム mymain.c があります。

ここに画像の説明を挿入

ここに画像の説明を挿入
gcc は mymain.c を通過して mymain.o を形成し、次に gcc -o を使用して 3 つの .o ファイルをリンクします。

ここに画像の説明を挿入

これは、ライブラリの基本的な実装原則です。しかし、この方法で書くのは十分に効率的ではありません。

ここに画像の説明を挿入

ar は静的ライブラリをパッケージ化し、-r は置換します。.o ファイルの作成後にソース コードが変更された場合は、このコマンドを使用します。-c は作成です。次に、それをユーザー ディレクトリにコピーし、その中の .o ファイルを削除します。

ここに画像の説明を挿入

ただし、このライブラリは直接使用できないため、現在コンパイルすることはできず、リンク エラーが報告されます。私たちがしなければならないことは、コンパイラーにライブラリー・ファイルとヘッダー・ファイルを見つけさせることです。今書いたライブラリはサードパーティのライブラリで、gcc g++ はこのライブラリを知りませんが、C++ ライブラリは知っています。ユーザーは、リンクするライブラリを gcc に知らせる必要があります。そうしないと、OS がそれを単独で認識できなくなります。

今すぐ gcc に知らせてください

gcc -o mytest mymain.c -L . -l mymath

大文字と小文字の l はどちらもリンクを意味しますが、-L は検索するパスを意味し、-l の後には lib プレフィックスを除いたライブラリが続き、途中のスペースは省略できます。

しかし、これは実際には図書館に与えられるものではありません。

ユーザーディレクトリには mymian.c が 1 つだけあります。

cp *.h include/
cp *.a lib
tar -czf mymath.tgz include lib
cp mymath.tgz …/otherperson
tar xzf mymath.tgz

最後のステップでパッケージを解凍すると、2 つのディレクトリが取得されます。 gcc -o mytest mymain.c -I ./include -L ./lib -l mymath は、実行可能ファイル mytest を生成できます。

しかし実際はそうではないでしょう。どちらのファイルもデフォルトの検索パスに配置されます

sudo cp -rf include/* /usr/include/
sudo cp lib/* /lib64

このとき、gcc が必要ない場合はライブラリをマークする必要はありません。ただし、このライブラリは依然としてサードパーティ ライブラリであり、gcc mymain.c -lmymath が必要です。

ライブラリの使用
1. ヘッダー ファイルとライブラリ ファイルを指定する必要があります
。 2. gcc および g++ のデフォルトの検索パスにインストールされていない場合、ユーザーは対応するオプションを指定してコンパイラーにヘッダー ファイルとライブラリ ファイルの場所を指示する必要があります。 、そしてライブラリファイルはどこにありますか?どこにありますか?
3. ダウンロードしたライブラリとヘッダー ファイルをシステムのデフォルト パス (Linux インストール ライブラリ) にコピーします。インストールとアンインストールの本質は、システム固有のパスにコピーすることです。
4. インストールされたライブラリがサードパーティのライブラリ (言語とオペレーティング システム インターフェイスがファースト パーティとセカンド パーティである) の場合は、通常どおり使用する必要があります。たとえシステムに完全にインストールされていたとしても、gcc/g++ は -l を使用して特定のライブラリの名前を指定する必要があります。これは保存できません

ダウンロードしたライブラリまたはソース コード (コンパイル方法) のいずれであっても、システム パスにコピーされるインストール コマンドが提供されます。すべてのインストール手順とライブラリにはスーパーユーザー (root) 権限が必要です。

2. ダイナミックライブラリ

まだ .o ファイルを作成中ですが、コマンドが異なります

gcc -fPIC -c myadd.c

ここでは、位置に依存しないコードを含むファイルを生成する必要があります。位置に依存しないコードは最後に書き込まれ、残りの操作は同じです。ただし、それを gcc でパックするだけです

ここに画像の説明を挿入

「shared」とは、共有された動的ライブラリを意味します。次に、2 つのディレクトリを作成し、include に .h を入れ、ダイナミック ライブラリを lib に入れてパックし、それをユーザーに渡します。ユーザーはそれを解凍し、2 つのディレクトリをデフォルトの検索パスの下に置き、必要な情報を入力します。 gcc の後に入力すると、実行可能プログラムが出てきます。

しかし、実行できず、エラーが発生し、使用可能なディレクトリがないというエラーが報告されます。

コンパイラにはライブラリの場所を伝えたつもりですが、オペレーティング システムにはライブラリがインストールされていないことを伝えていないため、実行時にエラーが発生します。ただし、静的ライブラリの接続原則は、ユーザーが使用するバイナリ コードをターゲットの実行可能プログラムに直接コピーすることであるため、静的ライブラリは見つかりますが、動的ライブラリは見つかりません。

オペレーティング システムは実行時に動的ライブラリをどのように見つけますか?


1. 環境変数 LD_LIBRARY_PATH を確認し、 export LD_LIBRARY_PATH=$LD_LIBRARY_PATH: path を入力して、再度実行します (環境変数は再ログイン後に復元されるため、一時的な解決策です)。

2. so ln -s path/libmymath.so /lib64/libmymath.so。これは、システムのパス下にソフトリンクを確立するためです。または、lib64 を選択できず、/ の後に作成される名前を記述します。再度ログインしても問題ありません。

3. 設定ファイルのスキーム

システムには設定ファイル ls /etc/ld.so.conf.d/ があります。ここで別のファイルを作成し、ファイルを開いてダイナミック ライブラリのパスを書き込むと、sudo ldconfig ですべての設定ファイルが有効になります。

4. ダイナミックライブラリのロード

以前の Linux ブログで述べたように、動的ライブラリを削除しても意味がなく、静的ライブラリを削除することもできます。

静的リンクによって形成される実行可能プログラムには、静的ライブラリの対応するメソッドが実装されています。複数のプログラムがある場合、同じコードが繰り返し出現することになり、多くのリソースを消費します。

ダイナミック ライブラリのリンクは、実行可能プログラム内の外部シンボルをライブラリ内の特定のアドレスに置き換えます。プログラムはコピーされるのではなく、置き換えられます。プログラムがメモリにロードされた後、プログラムはプロセスになり、プログラムの実行時にプロセスの PCB が作成され、アドレス空間のコード領域にプロセスのアドレス空間、マッピング関係などが作成されます。 printf などの構文へのマッピング関係は、ページ テーブルを通じて検索され、物理空間を検索し、そのような printf が存在しないことがわかります。このとき、システムは printf が特定のライブラリ ファイル内にあることを検出します。ダイナミック ライブラリの場合、ダイナミック ライブラリは物理メモリにロードされ、ダイナミック ライブラリはスタック領域とヒープ領域の間の共有領域であるアドレス空間内の場所にマッピングされます。は、現時点ではダイナミック ライブラリの対応する部分でもあります。これらはすべてオペレーティング システムによって自動的に行われ、マッピング関係が再確立されると、アドレス空間で printf に遭遇すると、ダイナミック ライブラリが配置されている空間を見つけて、コード領域に戻ってマップされます。は関数 Jump と同等で、アドレス空間内でのみジャンプします。

別のプロセスをロードした後も、上記の操作が続きます。したがって、メモリにコピーを 1 つ保存するだけで済み、その後、各呼び出しを独自のアドレス空間のダイナミック ライブラリに追加するだけです。

ライブラリは実際にはファイルであり、システムはファイルをロードするのと同じようにライブラリをロードします。

プログラムが翻訳およびリンクされて実行可能プログラムが形成されるとき、実行可能プログラム内にアドレスは存在しますか? プログラムがシステムによってメモリにロードされていないときは、プログラムにはアドレスがあるため、実行可能プログラムにコンパイルされるときには、すでに内部にアドレスがありますが、これは仮想アドレスです。

アドレスには絶対アドレッシングと相対アドレッシングがあり、プログラムの絶対アドレッシングにスタティックライブラリが組み込まれている、ダイナミックライブラリに問題がある、プロセスごとに動作度が異なる、使用するサードパーティライブラリが異なるしたがって、各プロセスの共有領域の空き場所は不定です。ダイナミック ライブラリ内のすべてのアドレスはオフセットであり、デフォルトではアドレス 0 から始まることがわかります。オフセットは、ライブラリがアドレス空間にマップされるときに決定されます。printfを実行すると、ダイナミックライブラリファイルの実開始アドレス+オフセットから該当するコードが検索されます。これは位置に依存しないコードです。

ダイナミック ライブラリとスタティック ライブラリが同時に存在します。システムはデフォルトでダイナミック リンクを使用します。ライブラリを決定するために gcc + いくつかのコマンドを実行した後、スタティック ライブラリを使用するためにスペース -static を追加します。静的ライブラリのみがある場合、作成されるファイルは静的ライブラリ ファイルです。

クラウドサーバーは通常、動的ライブラリを提供しますが、c の静的ライブラリをインストールする場合は、yum install -y glibc-static を実行します。C++ の場合は、yum install -y libc+±static です。

仕上げる。

おすすめ

転載: blog.csdn.net/kongqizyd146/article/details/129903073