Shared Libraryの概要

5404 ワード

共有ライブラリ、すなわちプログラム起動時に動的にロードされるライブラリファイル.共有ライブラリを合理的に使用することで,コードの再利用を効率的に実現できる.
プログラミング要件
単純な4つの演算を実現するライブラリファイルvmathがあるとします.
/* vmath.h */
#ifndef VMATH_H
#define VMATH_H

extern int vm_add(int, int);
extern int vm_sub(int, int);
extern int vm_mul(int, int);
extern int vm_div(int, int);

#endif

各関数の具体的な実現は以下の通りである.
/* vmath.c */
#include "vmath.h"

int vm_add(int op1, int op2) {
  return op1 + op2;
}

int vm_sub(int op1, int op2) {
  return op1 - op2;
}

int vm_mul(int op1, int op2) {
  return op1 * op2;
}

int vm_div(int op1, int op2) {
  int res;
  if (op2 != 0) {
    res = op1 / op2;
  }
  return res;
}

簡単なコードなので、あまり説明しません.このvmathライブラリを借りて簡単な4つの演算を実現したいプログラムがあります.
/* vm_test.c */
#include <stdio.h>
#include "vmath.h"

int main(int argc, char *argv[]) {
  int op1, op2;

  if (argc != 3) {
    fprintf(stderr, "Usage: %s <op1> <op2>
", argv[0]);     return -1;   }   sscanf(argv[1], "%d", &op1);   sscanf(argv[2], "%d", &op2);   printf("Operand #1: %d
", op1);   printf("Operand #2: %d
", op2);   printf("Addition: %d
", vm_add(op1, op2));   printf("Subtraction: %d
", vm_sub(op1, op2));   printf("Multiplication: %d
", vm_mul(op1, op2));   printf("Division: %d
", vm_div(op1, op2));   printf("Fin
");   return 0; }

プログラムヘッダにvmathのヘッダファイルvmath.hが埋め込まれているのを見た.プログラムはmain関数の2つのパラメータ:argv[1]とargv[2]を読み出し、それらをintに変換し、op 1とop 2に保存し、次にvmathの関数を呼び出すことによって、彼らの和、差、積、商を順次計算する.
共有ライブラリの生成
では、vmathが共有ライブラリとして存在することを望んでいます.コンパイル手順は静的ライブラリよりも少し異なります.まず、vmath.cをコンパイルします.
gcc -c -fPIC vmath.c -o vmath.o

コンパイラは懸念なくvmath.oオブジェクトファイルを生成し、次に.oファイルを.soファイルに変換する必要があります.s、shared:
gcc -shared -Wl,-soname,libvmath.so.1 vmath.o -o libvmath.so.1.0.0

現在のディレクトリの下で瞬間的に1つのファイルlibvmath.so.1.0.0を多く出して、つまり私たちの共有ライブラリのファイル、完成しました!なんだよ!これはあり得ない・・・
上記のコマンドを理解するには、まず共有ライブラリの3つの名前を理解する必要があります.
  • 共有ライブラリ名(Soname):名前の通り、ライブラリの名前で、標準フォーマットはlib+<ライブラリ名>+.so+.<マスターバージョン番号>です.私たちの共有ライブラリvmathを例にとると、そのsonameはlibvmath.so.1です.システムでは、sonameは通常、共有ライブラリの真の名前を指すリンク(Symbolic link)として存在する.
  • 実名(Real name):コードが本当に含まれるファイル名です.標準フォーマットは+.<サブバージョン番号>+.<発行番号>です.共有ライブラリvmathの本名はlibvmath.so.1.0.0です.
  • 接続名(Linker name):コンパイラがプログラム接続フェーズで共有ライブラリを要求するときに使用する名前で、通常はバージョン番号を持たないsoname、vmathの接続名はlibvmath.soです.接続名もリンク形式で存在し、その共有ライブラリのsonameを指す.

  • 次に、vmath.oをlibvmath.so.1の共有ライブラリlibvmath.so.1.0.0としてsonameを生成する前のコンパイラコマンドを振り返ってみましょう.
    共有ライブラリlibvmath.so.1.0.0を入手しました.次に、Sonameとlinker nameを追加します.
    ln -sf libvmath.so.1.0.0 libvmath.so.1
    ln -sf libvmath.so.1 libvmath.so

    前者はlibvmath.so.1.0.0へのリンクlibvmath.so.1、すなわち共有ライブラリのsonameを生成し、後者はlibvmath.so.1へのリンクlibvmath.so、すなわち共有ライブラリのlinker nameを生成する.
    準備万端、次はテストプログラムvm_test.cのコンパイル:
    gcc -c vm_test.c -o vm_test.o
    gcc -L. -lvmath vm_test.o -o vm_test

    -L現在のディレクトリである共有ライブラリのパスを指定します.-l必要な共有ライブラリを指定し、コンパイラが-lvmathに読み込むと、指定したパス内でlibvmath.soが自動的に見つかります.このように適切にコンパイルして、次に実行してみましょう.
    ./vm_test 12 3
    ./vm_test: error while loading shared libraries: libvmath.so.1: cannot open shared object file: No such file or directory

    妹さん!明らかにvm_testは起動中に共有ライブラリが見つかりませんでした.以前はgcc接続フェーズで共有ライブラリの所在と名前を指定しただけでしたが、最終的に生成されたプログラム自体は、共有ライブラリに関する情報を知りませんでした.プログラムが起動したときに共有ライブラリをスムーズに見つけるために、一連の方法を講じることができます.
    共有ライブラリの呼び出し
    LD_LIBRARY_PATH
    第1の方法は、環境変数LD_を介してLIBRARY_PATHは、共有ライブラリの場所を指定します.
    export LD_LIBRARY_PATH=/home/vesontio/devel/lib:$LD_LIBRARY_PATH
    ./vm_test 12 3
    Operand #1: 12
    Operand #2: 3
    Addition: 15
    Subtraction: 9
    Multiplication: 36
    Division: 4
    Fin

    ここではexportで共有ライブラリがあるパスを環境変数LDに保存します.LIBRARY_PATH,ここでは共有ライブラリファイルlibvmath.so.1.0.0とそのsonameが/home/vesontio/devel/libの下に保存されていると仮定する.そしてvm_を実行しようとしますtest、妥当です.
    rpath
    2つ目の方法は、rpath、すなわちruntime search pathを使用することであり、実行可能なファイルにハードに書き込まれたパスであり、プログラムが実行時に必要なライブラリファイルを探すのを助ける.rpathは実行可能ファイルのコンパイル時に指定される必要があります.vm_を再生成します.test:
    gcc -L. -lvmath -Wl,-rpath=/home/vesontio/devel/lib vm_test.o -o vm_test
    unset LD_LIBRARY_PATH
    ./vm_test 12 3
    Operand #1: 12
    Operand #2: 3
    Addition: 15
    Subtraction: 9
    Multiplication: 36
    Division: 4
    Fin

    vm_を再生成しましたtest、コマンドパラメータの唯一の違いは、-rpathで共有ライブラリが存在するパスを指定することです.試運転前に、環境変数LDをわざと削除しました.LIBRARY_PATHですが、共有ライブラリのパスが実行可能ファイルに書かれているため、プログラムは依然として華麗に実行されています.だからvm_testはLDを借りる必要はありませんLIBRARY_PATHはlibvmath.so.1を探しに来ました.
    ldconfig
    ldconfigはLinuxシステムの下でライブラリを共有する管理ツールであり、システム内のアプリケーションが必要な共有ライブラリを検索するのに役立ちます.ldconfigはデフォルトで、/libおよび/usr/libを含む標準的な共有ライブラリパスを検索しますが、共有ライブラリが他の場所に配置されている場合は、ldconfigのプロファイル、すなわち/etc/ld.so.confを手動で変更する必要があります.
    su
    vim /etc/ld.so.conf

    ldconfigのプロファイルを変更するには、管理者root権限が必要です.suでログインした後、共有ライブラリのパスをld.so.confに書き込み、ldconfigのキャッシュをリフレッシュします.
    ldconfig

    今からvm_を実行しますtest:
    ./vm_test 12 3
    Operand #1: 12
    Operand #2: 3
    Addition: 15
    Subtraction: 9
    Multiplication: 36
    Division: 4
    Fin

    またいいよ.ただし、ldconfigは実行時に共有ライブラリを探すのに役立つだけですが、gccの接続フェーズでは、手動で-Lで共有ライブラリのパスを指定し、-lで必要な共有ライブラリを指定する必要があります.
    以上の3つの方法はいずれも共有ライブラリの呼び出しを実現することができ,どの方法がより適切かは開発者自身のニーズに応じて,実際の状況に応じて決定する.