トップページ>>>「ぷろぐらみんぐ」目次

プログラマーでない人のための「共有ライブラリ」講座

初版作成:2003/01/11
2015年時点での参考資料追記:2015/06/29

目次

  1. 前書き
  2. 本題
  3. 後書き或いは感想
  4. 2015年時点での参考・推薦資料

前書き


2015年時点での、より正確で分かりやすい参考書籍の紹介を追記しましたので、そちらもぜひご確認ください。

 LinuxやUNIXを扱っていると「共有ライブラリ(shared library)」「ライブラリ(library)」という言葉をしばしば耳に します。特に、最新版を使おうとソースコードから見よう見まねでビルド、コンパイルとやらをおそるおそる行っては見たものの 見事に失敗したときや、或いは上手く動かないときのログファイル中で現れることもあります。

 プログラマーであれば、例え初めてLinuxに触ったとしても何となく語感だけでぼんやりと原因が想像できます。
 しかしごく普通の ---つまりプログラミングなどに興味関心も無かった--- 人たちにとって、「何だそりゃ、しらねーよ。」 な世界です(以前、パソコンに全く興味のない身内にプログラミング関連の愚痴を垂れたところ「日本語で話してくれ」と言わ れたことがあります)。

 今回の特別講座では、Windowsから移ってきたばっかりの、非プログラマー向けにこの「ライブ ラリ」がいったい何者なのか。
 そして「/lib」、「/usr/lib」下の大量のシンボリックリンクと「lib****.so.***」はいったい何か を適当に話していきたいと思います。

 今回の話をお読みいただき、少しでもLinux/UNIXシステムに対する不安が解消されればひっじょーにうれしいかな、と。
 ちなみに「何でおまえを喜ばせるためにわざわざ貴重な時間を割いてまでこんな初心者の書いた文書読まないかんのだ」とか言う つっこみはイタすぎですので無視させていただきます。

 ぶっちゃけた話、「プログラマーである自分自身が後学を兼ねてまとめた自分自身用レポート」なのはいつものことです から・・・。

参考資料
JFドキュメント「Program Library HOWTO」
・その他各種コマンドのmanページ

目次に戻る

本題

  1. まずは Windows に戻りましょう。
  2. DLLについて。
  3. 例え話も程々に。
  4. Linux/UNIX へ。
  5. Linux/UNIX 特有のお約束。

まずは Windows に戻りましょう。
「本題」に戻る

 生粋の Linux/UNIX ユーザーはこの文章は読んでいない、と仮定して大胆にも一旦話を Windows に引き戻します。
 というのは、最近になってLinux/UNIXをいじり始めた人たちは大半が Windows も使っている人たちであろうからです。

 んで。Windows でもやっぱり「共有ライブラリ」や「ライブラリ」といった言葉が頻発するわけです。が、何故かLinux/UNIX 程には恐怖感がありません。
 まずはそこから入っていきましょうか。

 単刀直入に切り出します。「共有ライブラリ」や「ライブラリ」と言われているシロモノの実体は単なるファイルです。
 で、Windows では「****.dll」、Linux/UNIX では「lib****.so.****」というファイル名(*の部分はライブラリの名前 何かが入ります。つまり何でも良い)が「共有ライブラリ」や「ライブラリ」といわれているシロモノの本体です。

 ほら、Windows で言うところの悪名高いVBランタイムライブラリ何かがまさにそれですよ。
 すこし Windows に詳しくなれば誰もが口にする「DLL」というのが、Windows 版の「共有ライブラリ」です(後述します がDLLファイルは「ライブラリ」とはちょっと違う場合もあります)。

 Windows を始めた頃を思い出して下さい。うっかり「****.dll」を削除してしまったばっかりに重要なアプリケーションが起動 しなくなったりしたこと、ありませんか?あれと同様の事が Linux/UNIX でも起こりうるのです。
 もっともLinux/UNIXシステムの場合、システム中枢に関わるライブラリは root 権限がないと消去できないパーミッションが 与えられていますのでおいそれとは(サーバーマシンなどでは)上記のような現象は起こらないでしょうが・・・。
 Linux/UNIX ではむしろ、「ライブラリのバージョンが違うために動作しない」現象の方が圧倒的に多いと思われます。

 そういえば、VBランタイムライブラリにも「VB5」とか「VB6」みたくバージョンがありました ねえ。フリーソフトなどを利用するときはVBランタイムライブラリのバージョンが違って動かなかった、みたいなこと。経験 しませんでした?

 話がまとまりませんが、「あ、共有ライブラリとかって Windows で言うところの DLL か!」と 頭の上にろうそくが灯って頂ければ十分かな、と。

DLLについて。
「本題」に戻る

 何だかとりとめない話になってしまいし、「何でLinux/UNIXでは共有ライブラリに対する恐怖感を覚えるのか」が終わっていません。

 これは人によりけりですので、どうせ(私個人が)汎用的(だと思っている)な理由を挙げても大した足しにはなりません。
 ここでは私自身がなぜ恐怖感を覚えたのか語らせていただきます。

 私が「共有ライブラリ」に出会ったのはやっぱりWindowsで、DLLファイルを削除してしまった事件でした。
 エラーメッセージが表示されたんですよね。「****.dllが見つかりません」みたいな。
 んで、(幸いにも)ゴミ箱に入れてた ****.dll を元に戻したら動くようになりました。

 私自身はプログラミングを勉強中でした。特にC言語を学んでいたせいもあってか、「DLL」の意味するところが朧気ながら(当然 誤解も含めて)直感的に察しがついていました。何となく、複数のアプリケーションから使用される機能の固まりではないか な、と。まあ、パソコン雑誌を拾い読みしていたせいもありましたが。

 そう言うわけで、Windowsでは大規模なアプリケーションにはDLLが使われているんだな、ということ。そして、「DLLファイルは 大概、C:\WINDOWSディレクトリの中か、個別のアプリケーションのフォルダの中にあるんだな。」ということをフリーソフトの インストール作業から学びました。
 現実問題として DLL 絡みの問題があまり起こらなかったということもあるのかもしれません。

 で、Linux/UNIXです。
 やっぱり最初、「ライブラリって何だっぺ」状態でした。
 C言語の知識から、「やっぱりコンパイル時に使うものだろうか」とか、「それとも Windows のDLLみたいなものじゃろか」とか。

 実は Windows において(特にプログラミングに於いて)「ライブラリ」と「共有ライブラリ」は相当意味が違うシロモノ なのです(詳細は後述)。
 それが、Linux/UNIXではずいぶんとごちゃ混ぜに使われています。その時点ですでに若干の混乱を引き起こしていました。

 極めつけは /lib ディレクトリ内にある大量の「lib****.so.****」ファイルとそれへのリンク。
 実例を下に示します。ls -l から適当に引っ張ってきた部分です。

lrwxrwxrwx    1 root     root           11  9月 10日 07:25 libpam.so -> libpam.so.0*
lrwxrwxrwx    1 root     root           14  9月 10日 07:25 libpam.so.0 -> libpam.so.0.75*
-rwxr-xr-x    1 root     root        38656  4月 28日  2002 libpam.so.0.75*

 どれがどうリンクしてるのかさっぱり分からん!!というか、なんでわざわざこんなにリンク張る必要が あるわけ!?
 リンクはWindowsで言うところのショートカットにあたります。
 ですが・・・なんでこんなにリンクを張ってるのか、全く謎でした。今まで。

 しかもですね。/lib, /usr/lib, /usr/local/lib と分散してしまっている・・・
 Windows と共有ライブラリの配置に対する哲学がまるで異なっています。

 Windows ではDLLは大抵 C:\WINDOWS(NT/2000では C:\WINNT)か、アプリケーション固有のディレクトリにまとめられます。
 ところが Linux/UNIX ではアプリ固有だろうと何だろうと見境なしに /lib, /usr/lib ディレクトリにつっこまれてる ので、分散してしまって分かりづらかったんです。

 いえ、分かりづらかったわけではありません。選択肢は /lib, /usr/lib, /usr/local/lib の三つしか無いわけですから。
 どちらかというと

居こごちが悪かった。

 というわけです。全てが「何となく想像はつくんだけど・・・でも何でこうなってんの?」という疑問で埋め尽くされている わけです。
 そんなわけで、JFのドキュメントに出会った今日までずっともやもやした不安というか気持ち悪さが Linux/UNIX の共有ライブラリ にはあったわけです。

つまり Linux/UNIX の哲学に慣れていなかった。

 慣れた者がちです、この世界。一旦慣れれば(自転車を初めて一人で乗れるようになった子供のように)応用や新しい方向への チャレンジへの道が開けますし、少なくとも目の前の靄の一つくらいは吹き飛ばせるはずです。

 というわけで、そろそろ「だーかーら、ライブラリってなんなんだよ!!!」と喚きたくなった 頃合いでしょうか。では。例え話を用いてライブラリの本質を語らせていただきます。

例え話も程々に。
「本題」に戻る

 私は今大変狂喜しています。というのは、私自身今まであやふやだった「ライブラリ」「共有ライブラリ」を相当日常生活に 例えた形で解説できる機会に出会えたからです。多くのユーザーが心の隅で抱いて居るであろう、この謎についてなぜ今まで これほどわかりやすい例えが用いられなかったのか不思議に思う(以下めんどいので削除)

 ライブラリを語る前に、まずそもそもみなさんが日常使っている「アプリケーションソフト」とは何なのかの説明から始めましょう。

 アプリケーションソフト、サーバー、デーモン・・・。色々呼び名はありますが、一般にソフトウェア本体とされているファイルが Windowsにも、Linux/UNIX にも存在します。
 よーするにWindowsではアイコンをダブルクリックするとアプリケーションが起動するファイルで拡張子が「EXE」のやつ。
 Linux/UNIXの場合はシェルから直接打ち込むことにより何らかのソフトが起動するファイルです。

 これらは「実行形式のファイル」とも呼ばれています。
 ぶっちゃけた話、パソコンのCPUが理解できる言語で書かれた処理手順書です。
 そのアプリケーションが何をどうするか。それを記述した手順書が実行形式ファイルです。
 CPUつまり中央処理装置は全てを数値で処理します。それを直接人間が書こうとするにはとてつもない知識と技量が必要になります (まれにそれをやってのけてしまう人種も居ます。OSの開発者達です)。

 とにかく、CPUにだけ分かる言語で「最初にあーしろ、次どーしろ、もしユーザーがこのボタンクリックしたらこーしろ・・・」 といった処理手順が書き連なったファイルが「実行形式のファイル」と呼ばれるものです。

 これは料理で言えば一種のレシビ、職人さんなら一種の設計図にあたります。

 で、こっからが話の本題です。
 もっともわかりやすいレシピ(または設計図)は一つのレシピ(または設計図)に、必要な処理手順が逐一書かれている 状態でしょう。そのレシピさえ見れば、包丁の使い方からジャガイモの皮の向き方、おまけに食器の後かたづけ方法まで全て載っている わけです。
 ところが、全てのレシピに対していちいちそこまで記述するのは(もしそのレシピが紙で出来ているなら)紙の無駄遣いですし、 何よりも慣れてくると鬱陶しくなります。
 そこで、包丁の握り方やキャベツの千切り方法など、殆どのレシピでおよそ共通している部分を抜き出します。

 この抜き取った共通部分のレシピこそが、ライブラリにあたります。

 ただし・・・もとのレシピに、「ここは他のレシピでも共通に使われてる部分だから切り抜いたよ。」という印が無かったら どうなるでしょうか。たとえば「三枚おろし」に関する部分が切り抜かれている状態で、「ここで三枚おろしにします。」 などという記述がレシピに出てきたらどうなるでしょう。

 人間なら「どっかに書かれてなかったかな」と他のレシピをめくりますが、CPUはそう言った自分で何か考える能力は文句無くゼロ です(仮にあるように見えても、それはレシピにそう振る舞うように指示が書かれていたからです)。
 というわけで、もし切り抜かれた共通部分(ライブラリ)が見つからないとCPUは「そんなこと知りませんよ。」とエラーを 発生してくれます。
 今回の例なら「三枚おろし?どうやるの、それ。」と自分で調べもせずに聞いてくる、あまつさえ多くの場合、そのままやる気を 無くしてレシピの料理を作ろうとするのを止めてしまいます。

 このようなとき、正しく「三枚おろしってのはこうするんだよ。」と教える方法はざっと3通りあります。

1.人間側で予め、レシピに「三枚おろし」の部分を糊とかで貼り付けて剥がれないように一体化してから CPUにレシピを渡す。

2.レシピに、「三枚おろしについて知りたければどこそこの本棚のこういうファイルに載っている」と、本体の レシピの冒頭部分に付け足してからCPUに渡す。

3.「三枚おろし」の記述が現れる時点でようやく「ここの本棚のこういうファイルに載っている」 という記述を付け足してからCPUに渡す。


 特に2.と3.の違いについて注意して下さい。2.では予め共通部分のレシピの存在箇所を冒頭で、まとめて書き付けて おきます。3.では、共通部分を使う段になって初めてその共通部分の存在箇所を教えています。

 実際にはこんな風なレシピを渡すことになります。
1.2.3.
材料:サンマ一匹
手順1:包丁を握ります。
・・・
手順2:サンマを三枚おろしにします。
魚をのせ、包丁を尻尾の方から...
...
...
手順3:...
・包丁の握り方についてはこういう名前のファイルに書き付けときました。
・三枚おろしの方法についてはこんな名前のファイルに書き付けときました。
材料:サンマ一匹
手順1:包丁を握ります。
手順2:サンマを三枚おろしにします。
手順3:...
材料:サンマ一匹
手順1:包丁を握ります。 ・包丁の握り方についてはこの名前のファイル名に。
また、包丁が果物包丁しか無い場合はこちらの名前のファイルに書き付けてあります。
手順2:サンマを三枚おろしにします。
・三枚おろしの方法についてはこんな名前のファイルを参照。
手順3:...


 まあ、こんな感じです。特に3.で、そのときの条件によって参照先を変えている事に注目して下さい。

Linux/UNIX へ。
「本題」に戻る

2015年時点での、より正確で分かりやすい参考書籍の紹介を追記しましたので、そちらもぜひご確認ください。

 まず、1.のレシピについて考えてみましょう。
 一番これが「手抜き」なレシピでもあります。単に共通部分をぺたりと貼り付けただけですから。
 ただ、もしも他のレシピにもこういったことをするとどうなるでしょう。レシピを作る度に共通部分をいちいち貼り付けていく 訳ですから、一つ二つのレシピしかCPUに渡さないのであればそうでもないでしょうが、数百のレシピをCPUに渡す事になると、 重複部分の無駄は無視できなくなってきます。
 他にもその三枚おろしの方法は自分の家では出来るやり方であっても(包丁の種類や職人の腕前など)、別の家に持っていっても 出来るとは限りません。

 そこで2.の出番です。共通部分を書き付けたファイル名を予め冒頭でリストしておきます。CPUは三枚おろしと出てきたら 冒頭のリストを参照し、どのファイルに書かれているか(ようやく自分で)調べに行きます(実はこれとて、とある共通部分に そうしなさいと書かれているから)。
 こうすれば1.で起こり得た重複部分の無駄は激減します。また、共通部分を書き付けたファイル名は一般にどの家でも一緒 (大抵の料理集にはそのままの名前で目次に載っている)です。そして、家毎に共通部分はカスタマイズしてある(はず)ので 2.のレシピを違う家のCPUに頼んでも、CPUはその家に応じた共通部分をとってきてくれるのでエラーになりません。
 デメリットとしては、共通部分に依存するレシピが多くなってしまい逆に共通部分を管理する負担が増えてくることです。
 またレシピの共通部分に依存する率が高くなるので、ちょっとした家の違いでも「この共通部分が無い」といった現象が発生 しやすくなります。
 それでも、家を管理している人たちがよく使われる共通部分をそれぞれしっかり管理していれば、よほどカスタマイズされた レシピを渡さない限り、大抵は問題なく料理してくれます。

 3.は、その場その場の条件によって、共通部分の参照先を変更できるメリットがあります。
 たとえば、包丁の握り方一つとっても和包丁、ナイフ、果物包丁、中華包丁・・・とあるわけです。
 そのときそのときの条件によって、「今日は和包丁」「昨日はナイフ」と柔軟に切り替えられます。つまり、問題へのアプローチ 方法がリアルタイムで複数存在するときに威力を発揮します。これこそがブラウザなどでお世話になるプラグイン の正体です。
 今回の例ではちょっと分かりづらいかもしれません。というのも、包丁の種類は家の違いと考えてしまえば別段、2.の方式 をとっても問題ないからです。
 非現実的ですが、マグロが材料に渡されてきたとしましょう。そうなってくると2.では対処が難しくなります。

 本マグロを捌くのは並大抵の技量では出来ません。とにかく、包丁からして普通のものでは無理です。
 しかし、家と家の間で互換性を維持するためには、「包丁が無い」からといって終わりにするのはよくありません。
 むしろこの場合、「包丁はどうでも良い。むしろ、その場にある包丁でどう捌くか」という捌く手順を複数用意します。

 ・・・よくよく考えるとこれは2.でも出来てしまいます。つまり、今回は「材料として渡された魚に応じて捌き方を変える」 必要があるのです。これは2.では不可能です。2.では予め渡される材料が分かっているか、予測できる場合は有効です。しかし 全く未知の場合はいったいいくつの「**魚の捌き方」共通部分を冒頭に書き付けておく必要があるのでしょうか。
 こういうときこそ、3.の出番になります。こうすれば万事解決です。

・包丁の握り方は「houtyou_nigirikata.dll」ファイルに書き付けてあります。
材料:とりあえず魚一匹。
手順1:包丁を握ります。
手順2:魚を三枚おろしにします。
    もしも魚がサンマだった場合は「sabakikata_sannma.dll」ファイルに捌き方が載っています。
    もしも魚が本マグロだった場合は「sabakikata_honnmaguro.dll」ファイルに・・・
    もしも・・・
    というわけでとにかく魚を三枚おろしにします。
手順3:...

 もうちょっと改良を加えましょう。魚の種類と、捌き方を載せた共通部分(dllファイル)を対にした内容のファイルを作っておきます。

ファイル名:「tui_sakana_sabakikata.txt」
サンマ:sabakikata_sannma.dll
本マグロ:sabakikata_honnmaguro.dll
イワシ:sabakikata_iwasi.dll
...

 そして、いざ三枚に下ろすときにこのファイルを参照して、対応するDLLをロードするようにすればいいのです。

(省略) 手順2:魚を三枚に下ろします。
    魚の種類と捌き方を載せたファイルの対応表は「tui_sakana_sabakikata.txt」にあります。
    それみて適切な捌き方を調べて下さい。
    というわけでとにかく魚を三枚おろしにします。
手順3:...

 こうすれば新しい魚が入ってきたときでも対応表に、対応するDLLを書き付けるだけで対処できるようになります。
 まさしく「魚の三枚おろし」に関するプラグインシステムを作ってきたわけです。


 以上、1.、2.、3.と全く同じ仕組みが Windows, Linux/UNIX 両OSに備わっています。
 各レシピの共通部分が Windows で言うところの DLLファイル であり、Linux/UNIXでの 共有ライブラリ になることが実感して 頂けたでしょうか。

 ・・・Windowsの場合はDLLファイルであるのは周知の通りです。では、肝心のLinux/UNIXではどんなファイル名の命名規則が 使われているのか。そして、なぜlib****.so****はあんなにリンクが張ってあり、しかも分散しているのか。
 引き続きこの謎に迫っていきたいと思います。

Linux/UNIX 特有のお約束。
「本題」に戻る

 ここでは、主に「命名規則」と「配置場所」に絞ってお話しします。
 まずは命名規則からです。

 共有ライブラリのファイル名は次の形式に従ってリンクファイルを含めて作成する必要があります。
 下に示す例の「****」の部分はそのライブラリを表す文字列が入ります。たとえばlibpam.soはPAMを実装するためのライブラリです。

ファイル名の形式自体の名前ファイル名の形式リンク先
real namelib****.so.(メジャー番号).(マイナー番号群) libhogehoge.so.2.0.1.2(共有ライブラリ本体なのでリンク先は無し)
sonamelib****.so.(メジャー番号)libhogehoge.so.2libhogehoge.so.2.0.1.2
linker namelib****.solibhogehoge.solibhogehoge.so.2


 ・・・何でこんな事になっちゃったんでしょう。その原因は、Linux/UNIXの実行ファイル形式にあります。

 先ほどの例えで、「(ようやく自分で)調べに行きます(実はこれとて、とある共通部分にそうしなさいと書かれているから)」 とあった部分を思い出して下さい。この「とある共通部分」が「プログラムローダー」や「リンカローダー」と呼ばれる部分です。
 このプログラムローダー(ld-linux.so)は前述の命名規則に従っていない、超特別な共通部分です。

 先ほどの例えで言うと、まさに「人間の読めるレシピからCPUの読めるレシピに変換する」ときデフォルトで冒頭に宣言 される共通部分です。これがないと、他の共通部分をCPUが読み込めないほどの重要な部分です。

 で、上に挙げた命名規則やリンク生成はこのプログラムローダーの仕様に基づきます。

 さて。人間の読めるレシピからCPUの読めるレシピに変換する(以降、この動作を「コンパイルする」と言います)時、使用する 共有ライブラリ名を「-l****」(上の例なら -lhogehoge)とする事がプログラムローダーの仕様になっています。
 ****はすなわち、linker nameのlib****.soに該当します(メジャー番号を無視してますし)。するとリンク先のsonameが プログラムの内部で使われるようにな(るらしい)ります。

 んで。この段階ではライブラリの「ファイル名」は判明しても「ディレクトリ」が分かりません。実はLinux/UNIXには「/sbin/ ldconfig」というコマンドがあります。このコマンドが(設定ファイルに登録済みの)ディレクトリを検索し、ライブラリの 「ファイル名」とそのディレクトリ位置を目録化してくれます。この目録は/etc/ld.so.cacheファイルに格納 されます。
 で、この目録の作成に使われる「ファイル名」が soname なわけです。んで、プログラムからプログラムローダ、そして ファイルシステム上のリンクをたどってようやく realname に至るわけです。

 とにかく、プログラムローダーとldconfigの仕様によって2種類のリンクを作成する必要があったわけです。

 次に配置場所について解説します。今までの説明ですと、プログラム内部で共有ライブラリを指定するときはsonameを 使います。が、これだけですと「どのディレクトリにあるのか」が分かりません。そのために、sonameを検索するときのインデックス として/etc/ld.so.cacheがあり、そのインデックスを更新するのが/sbin/ldconfigでした。
 で。実際にldconfigはどのディレクトリを検索してインデックスを作成しているのか。検索するディレクトリをリストしたのが 「/etc/ld.so.conf」ファイルです。これは単純なテキストファイルです。私の(TLXW8)を載っけます。
[fenjin@seisyuu fenjin]$ cat /etc/ld.so.conf
/usr/X11R6/lib
/usr/lib/gconv
/usr/lib/qt/lib
/usr/local/lib
/usr/i386-linuxaout/lib
/usr/lib/libc5-compat
/usr/lib/sane
/usr/lib/Omni
[fenjin@seisyuu fenjin]$

 ・・・「/lib」や「/usr/lib」はどこ行ったのでしょう。実はこの二つのディレクトリはldconfigがデフォルトで必ず チェックするディレクトリです。そのため、わざわざ/etc/ld.so.confに記述する必要がない訳です。
 /usr/local/libもしっかり指定されています。実は、/usr/local/libはldconfigのデフォルトではありません(RHL6.2以降)。その ためわざわざld.so.confに記述する必要があったわけです。

 結局、パターンさえ掴めてしまえばWindowsと同じか、それ以上にきめ細かくライブラリを管理できるというへんてこな 具合になってしまいます。
 なぜならライブラリの指定に用いているのはsonameですが、これはrealnameへのシンボリックリンクです。
 ということは、もしライブラリがバージョンアップされたときなどは、古いライブラリを上書きせずにリンクだけ 変更することによって、万が一に備えたライブラリのバージョンアップが出来るわけです。

 そして、ライブラリのインストール先は「/lib」「/usr/lib」、そして/etc/ld.so.confに記述されているディレクトリ内である ことも確実です(本当はLD_LIBRARY_PATH環境変数でローカルに変更もできるのですが)。

 まあこんな感じで、Linux/UNIXの共有ライブラリの仕組みは成り立っています。

目次に戻る

後書き或いは感想

 最後に、C言語における厳密な意味でのライブラリと共有ライブラリの違いについて言及しておきます。
 C言語ではコンパイルするときに一緒に抱き合わせるのがライブラリです。つまり、魚の三枚おろしで言う1.のパターンの時 用いている共通部分を「ライブラリ」といいます。拡張子が「.a」になっていることが大きな特徴です(Windowsでは「.lib」になっている場合が多い)。
 Linux/UNIX, Windowsで「共有ライブラリ」と言う場合、それは「.a」ファイルではありません。
 というのは、.aファイルはその他のメインプログラムに抱き合わされる事が予想されているため、.a自身が使用している 共通部分(printfとか)は.aには含めないようになっています。抱き合わせ先のメインプログラム側で一緒にしてくれる事を 予想されているからです。
 ところが共有ライブラリは、それ自体で完結するようになっています。共通部分としてのライブラリも(あたかもメイン プログラムと同等の存在であるかのように)きちんとリンクされて、lib****.so****が生成されるわけです(Windowsなら*.dll)。
 厳密な定義を追いかけるとこういった違いも出てきます。まあ、非プログラマの人たちにはおよそ関係ない話です。


 もしあなたがC/C++のプログラマ(学習者)で、共有ライブラリの実際のソースコードで実験したければ、本ページの前書きで 載せてあるJFドキュメントを参照すると良いでしょう。ここではプログラミングには一切立ち入らず話をしたため、物足りない向きは 当然あったと思われます。
 どちらにせよ、このページがあなたのLinux/UNIXのライブラリに対する漠とした不安感を幾分でも軽減できれば大変うれしいです。

2015年時点での参考・推薦資料

2015-06位に、こちらの記事への「はてなブックマーク」が急増しました。 参考にしていただけるのはありがたいのですが、なにしろ2003年頃に自身も勉強中の状態で、整理も兼ねて執筆した記事です。 比喩として適切でなかったり、そもそもこうした記事を読もうとする人達の技術レベルを考慮していなかったり、そもそも理解や記述に不正確・不十分な点もあります。

2015年現在、unix、特にLinuxでの共有ライブラリ(.soファイル)について、より正確かつ分かりやすく学べる書籍が出ています。 Linuxを使われていて、共有ライブラリ(.soファイル)の仕組みについて興味を持たれた方は、ぜひそちらの書籍で、より正確で分かりやすい文章で学んでいただくことを推奨します。

推奨書籍その1(基礎から解説されていますので、一番オススメ)

推奨書籍その2(よりgccコンパイラとELFフォーマットのディープな話題が多く、プログラマ中級〜上級者向け)

Windowsの場合のDLL(Dynamic Link Library)については、Visual C++開発者向けのドキュメントや、Microsoftからの解説資料が出ていますので、まずそちらを確認されることを推奨します。


※MSDN上のURLは時々サイト構成のアップデートで変化します。また、利用しているVisual C++/Visual Studioのバージョンと同じドキュメントを参照したほうが正確です。そのため、上記リンクがNot Foundになった場合や、ご利用のVisualC++/Visual Studioのバージョンと異なる場合は、お手数ですが検索しなおしてください。

Windowsの場合、EXEファイルやDLLファイルはPortable Executableフォーマット(PEフォーマット)という形式で構成されています。 DLLで使える色々な機能やオプションは、PEフォーマットと密接に関連しています。 そのため、DLLを学ぶにはPEフォーマットについても学んだほうがバランスが良いと思います。

2015-06時点で軽く検索したところ、日本語では以下の記事がオススメです。最初のvectorのHPについては2010年頃自分もPEフォーマットの勉強の際に参考にした記事です。


英語になってしまいますが、Matt Pietrek氏のPEフォーマットの解説も非常に詳しいです。PEファイルにリンクされる手前の、OBJファイルやLIBファイルについても解説されています。 ただしMSDN上の記事であり、サイト構成のリニューアルでURLが変わってしまいます。 以下の紹介記事のタイトルを参考に、MSDNの記事を検索してみてください。
"Matt Pietrek - MSDN & MSJ Articles" : http://www.wheaty.net/articles.htm

目次に戻る

トップページ>>>「ぷろぐらみんぐ」目次