GNU/Linux >> Linux の 問題 >  >> Linux

Linux 共有ライブラリの紹介 (共有ライブラリの作成方法)

ライブラリは、さまざまなオブジェクト ファイルからコンパイルされたコードを 1 つのファイルに詰め込んだファイルです。特定のコンテキストで使用される関数のグループが含まれている場合があります。たとえば、「pthread」ライブラリは、スレッド関連の関数がプログラムで使用される場合に使用されます。

大まかに、ライブラリ (またはプログラム ライブラリ) には次の 2 つのタイプがあります。

<オール>
  • 共有ライブラリ
  • 静的ライブラリ
  • この記事では、共有ライブラリについて具体的に説明します。

    共有ライブラリ

    共有ライブラリは、実行時に任意のプログラムにリンクできるライブラリです。これらは、メモリ内のどこにでもロードできるコードを使用する手段を提供します。ロードされた共有ライブラリ コードは、任意の数のプログラムで使用できます。したがって、このようにして、共有ライブラリの形式で多くのコードが共通に保たれるため、プログラムのサイズ (共有ライブラリを使用) とメモリ フットプリントを低く抑えることができます。

    共有ライブラリは、このライブラリを使用するアプリケーションを再コンパイルすることなく、ライブラリ コードを変更、修正、および再コンパイルできるため、開発環境にモジュール性を提供します。たとえば、pthread ライブラリ コードを変更しても、pthread 共有ライブラリを使用するプログラムを変更する必要はありません。共有ライブラリには、さまざまな名前でアクセスできます:

    • リンカーが使用する名前 (「lib」の後にライブラリ名が続き、その後に「.so」が続きます。たとえば、libpthread.so)
    • 完全修飾名または soname (「lib」の後にライブラリ名、「.so」、「.」、およびバージョン番号が続きます。例:libpthread.so.1)
    • 実際の名前 (「lib」の後にライブラリ名、「.so」、「.」とバージョン番号、「.」とマイナー番号、「.」とリリース番号. リリース番号はオプションです. 例:libpthread.so.1.1)

    コードで行われた変更によって共有ライブラリが以前のバージョンと互換性がなくなると、共有ライブラリのバージョン番号が変更されます。たとえば、関数が完全に削除された場合、新しいバージョンのライブラリが必要になります。

    マイナー番号は、使用されている以前のバージョンと互換性のない共有ライブラリを作成しないコードの変更がある場合に変更されます。たとえば、小さなバグ修正によって既存の共有ライブラリの互換性が損なわれることはないため、マイナー番号のみが変更され、バージョンは同じままです。

    では、なぜ共有ライブラリにこれほど多くの名前が付けられているのか疑問に思われるかもしれません。

    これらの命名規則は、同じ共有ライブラリの複数のバージョンがシステムに共存するのに役立ちます。共有ライブラリとリンクするプログラムは、システムにインストールされている共有ライブラリの最新バージョンを気にする必要はありません。共有ライブラリの最新バージョンが正常にインストールされると、すべてのプログラムが自動的に最新バージョンへのリンクを開始します。

    リンカーによって使用される名前は通常、完全修飾された soname へのシンボリック リンクであり、これは実際の名前へのシンボリック リンクです。

    ファイル システムへの配置

    ファイルシステムには、ライブラリを配置できる標準的な場所が主に 3 つあります。

    • /lib
    • /usr/lib
    • /usr/local/lib

    ここでは、ファイルシステム階層標準 (FHS) に従います。 FHS 標準に従って、起動時にロードされ、ルート ファイルシステムで実行されるすべてのライブラリは /lib に保持されます。システムが内部的に使用するライブラリは /usr/lib に保存されます。これらのライブラリは、ユーザーまたはシェル スクリプトが直接使用するためのものではありません。 3 番目の場所 /usr/local/lib があります (最新バージョンの FHS では定義されていません)。存在する場合は、標準配布に含まれていないすべてのライブラリが含まれています。これらの非標準ライブラリはダウンロードしたものであり、バグがある可能性があります。

    ldconfig の使用

    共有ライブラリが作成されたら、共有ライブラリをライブラリを配置するディレクトリ (たとえば、/usr/local/lib または /usr/lib) にコピーします。次に、このディレクトリで ldconfig コマンドを実行します。

    ldconfig は何をしますか?

    共有ライブラリのリンカー名は、完全修飾された soname へのシンボリック リンクであり、これは実際の名前へのシンボリック リンクであることを前に説明したことを思い出してください。このコマンドはまったく同じことを行います。

    ELF 実行可能ファイルを実行すると、デフォルトでローダーが最初に実行されます。ローダー自体は共有オブジェクト ファイル /lib/ld-linux.so.X で、「X」はバージョン番号です。このローダーは、プログラムが依存するすべての共有ライブラリを見つけてロードします。

    ライブラリを見つけるためにローダーによって検索されるすべてのディレクトリは、/etc/ld.so.conf に保存されます。 /etc/ld.so.conf ファイルで指定されたすべてのディレクトリを検索すると時間がかかる可能性があるため、ldconfig コマンドを実行するたびに、必要なシンボリック リンクが設定され、ファイル /etc/ld.so.cache にキャッシュが作成されます。実行可能ファイルに必要なすべての情報が書かれています。キャッシュからの情報の読み取りにかかる時間は非常に短くなります。ここでの問題は、共有ライブラリが追加または削除されるたびに ldconfig コマンドを実行する必要があることです。そのため、プログラムは起動時に /etc/ld.so.cache を使用して必要なライブラリをロードします。

    非標準のライブラリの場所の使用

    標準以外のライブラリの場所を使用する場合。次の 3 つの手順のいずれかを実行できます:

    /etc/ld.so.conf ファイルへのパスを追加します。このファイルには、ローダーがライブラリを検索するすべてのディレクトリへのパスが含まれています。このファイルには、次のような単一の行が含まれる場合があります:

    include /etc/ld.so.conf.d/*.conf

    その場合は、同じディレクトリに conf ファイルを作成するだけです。次のコマンドを使用して、ディレクトリをキャッシュに直接追加できます:

    ldconfig -n [non standard directory path containing shared library]

    これは一時的な変更であり、システムを再起動すると失われることに注意してください。環境変数 LD_LIBRARY_PATH を更新して、共有ライブラリを含むディレクトリを指すようにします。ローダーは、この環境変数で指定されたパスを使用して依存関係を解決します。

    一部の Unix システムでは、環境変数の名前が異なる場合があることに注意してください。

    注:関連トピックについては、以前に説明したように、ソース コードが最終的に実行可能ファイルになるまでに 4 つの主な段階があります。

    例 (共有ライブラリの作成方法)

    簡単な実用的な例を見て、共有ライブラリを作成して使用する方法を見てみましょう。以下は、共有ライブラリに入れたいコード (shared.c) です:

    #include "shared.h"
    unsigned int add(unsigned int a, unsigned int b)
    {
        printf("\n Inside add()\n");
        return (a+b);
    }

    shared.h は次のようになります:

    #include<stdio.h>
    extern unsigned int add(unsigned int a, unsigned int b);

    まず、shared.c を共有ライブラリとして作成しましょう。

    1. 次の 2 つのコマンドを実行して、共有ライブラリを作成します:

    gcc -c -Wall -Werror -fPIC shared.c
    gcc -shared -o libshared.so shared.o

    最初のコマンドはコード shared.c を、共有ライブラリに必要な位置に依存しないコードにコンパイルします。
    2 番目のコマンドは、実際には「libshared.so」という名前の共有ライブラリを作成します。

    2. 共有ライブラリ関数「add()」を使用するプログラムのコードは次のとおりです。

    #include<stdio.h>
    #include"shared.h"
    int main(void)
    {
        unsigned int a = 1;
        unsigned int b = 2;
        unsigned int result = 0;
    
        result = add(a,b);
    
        printf("\n The result is [%u]\n",result);
        return 0;
    }

    3. 次に、次のコマンドを実行します:

    gcc -L/home/himanshu/practice/ -Wall main.c -o main -lshared

    このコマンドは、main.c コードをコンパイルし、(フラグ -l を使用して) コードを共有ライブラリ libshared.so にリンクするよう gcc に指示し、共有ファイルの場所も (フラグ -L を使用して) 指示します。

    4. 次に、次のコマンドを使用して、新しく作成された共有ライブラリが保持されているパスをエクスポートします:

    export LD_LIBRARY_PATH=/home/himanshu/practice:$LD_LIBRARY_PATH

    上記のコマンドは、パスを環境変数「LD_LIBRARY_PATH」にエクスポートします。

    5. 実行可能ファイル「main」を実行します:

    # ./main
    
    Inside add()
    
    The result is [3]

    共有ライブラリがロードされ、その中の add 関数が実行されたことがわかります。


    Linux
    1. Linuxコマンドのスクリプトを作成する方法

    2. Linux で実行可能ファイルが使用するすべての共有ライブラリを表示するには?

    3. Linux で共有ライブラリの遅延ロードを行う方法

    1. Linuxですべてのユーザーの共有ディレクトリを作成する方法

    2. LinuxRPMパッケージを作成する方法

    3. Linuxでスワップを作成する方法

    1. LinuxでSystemdサービスを作成する方法

    2. Linuxでスワップファイルを作成する方法

    3. Linux で共有ライブラリを初期化する方法