Slide 1

Slide 1 text

コード再利用のしくみ ライブラリ Sep. 29th, 2024 Satoru Takeuchi X: satoru_takeuchi 1

Slide 2

Slide 2 text

はじめに ● 「ライブラリ」という、プログラムのコードをまとめて再利用可能にした塊について説 明 ● 注意 ○ ライブラリには実行ファイルと同様、コードとデータ両方が入っているが、説明を簡略化するため コードをどう扱うかのみ説明する 2

Slide 3

Slide 3 text

ライブラリとは ● 多くの人が使うコードを一つにまとめてファイル化したもの ● 有名どころ: GNUのCライブラリ、glibc ○ 標準Cライブラリ+その他山盛りの便利コード ● 実行ファイルとの違い ○ ライブラリファイルを直接実行するわけではない ○ 実行ファイル内のコードから何らかの形でライブラリのコードを呼ぶ ● 「静的ライブラリ」と「動的ライブラリ」の2種類がある 3

Slide 4

Slide 4 text

静的ライブラリと共有(動的)ライブラリ ● 静的ライブラリ ○ 実行ファイルにライブラリのコードを組み込む ○ ライブラリが提供する関数の中から、実行ファイルが使うものだけ組み込む ○ 拡張子は”.a” ● 共有(動的)ライブラリ ○ 実行ファイルには「ライブラリ内の関数を呼び出す」という情報だけ記憶 ○ 実行ファイルから作ったプロセスのメモリにライブラリのコードを「動的」にマップしてから呼び出す ○ 同じライブラリを複数の実行ファイルから実行時に「共有」できる ○ 拡張子は”.so” 4

Slide 5

Slide 5 text

こういうソースファイルがあった場合… 5 main() { foo() } main.c foo() { … } bar() { … } foo.c 呼ぶ

Slide 6

Slide 6 text

静的ライブラリの場合 6 main() { foo() } main.c foo() { … } bar() { } foo.c main()のコード main.o foo()のコード libfoo.a main()のコード main (実行ファイル) リンク コンパイル コンパイル&静的ライブラリ化 mainプロセスのメモリ空間 bar()のコード foo()のコード main()のコード foo()のコード map 呼ぶ 呼ぶ ● 実行前にリンク(静的リンク) ● 使用する関数だけをリンク可能

Slide 7

Slide 7 text

共有(動的)ライブラリの場合 7 main() { foo() } main.c foo() { … } bar() { } foo.c main()のコード main.o foo()のコード libfoo.so main()のコード main (実行ファイル) リンク コンパイル コンパイル&共有ライブラリ化 mainプロセスのメモリ空間 bar()のコード main()のコード foo()のコード map 呼ぶ 呼ぶ bar()のコード libfoo.soを動的 リンクしていると いう情報 実行開始後にリンク(動的リンク)

Slide 8

Slide 8 text

実行ファイルのサイズ ● 静的ライブラリ ○ ライブラリ内のコード (の一部)をコピーするので、一般に大きくなる ● 共有(動的)ライブラリ ○ 「実行時にライブラリを動的リンクすべし」というメタデータだけを持ち、ライブラリ内のコードそのも のは持たないので、一般に小さくなる 8 main()のコード main (実行ファイル) foo()のコード main()のコード main (実行ファイル) libfoo.soを動的 リンクしていると いう情報 静的ライブラリの場合 共有ライブラリの場合 一般に大きい 一般に小さい

Slide 9

Slide 9 text

ライブラリ変更の実行ファイルへの影響 ● 静的ライブラリ ○ ライブラリ修正後に再リンクした際に実行ファイルに影響が出る ● 共有(動的)ライブラリ ○ ライブラリ変更後、即座に実行ファイルに影響が出る ○ 変更の影響がライブラリを使用する全実行ファイルに及ぶので管理が大変 9 静的ライブラリの場合 共有ライブラリの場合 main()のコード main (実行ファイル) foo()のコード (バグ未修正) foo()のコード (バグ修正済) libfoo.a bar()のコード main()のコード main (実行ファイル) libfoo.soを動的 リンクしていると いう情報 foo()のコード (バグ修正済) libfoo.so bar()のコード

Slide 10

Slide 10 text

ライブラリファイル破損時の実行ファイルへの影響 ● 静的ライブラリ ○ 無い ● 共有(動的)ライブラリ ○ プロセスを起動してもライブラリの関数が使えないため、機能しない 10 main()のコード main (実行ファイル) foo()のコード foo()のコード libfoo.a bar()のコード あっそ 静的ライブラリの場合 共有ライブラリの場合 foo()のコード libfoo.so bar()のコード main()のコード main (実行ファイル) libfoo.soを動的 リンクしていると いう情報 死んだ! 死んだ! 俺も死んだ! リンク後はlibfoo.aに関係ない

Slide 11

Slide 11 text

ライセンスの観点 ● ライブラリを動的リンクするか静的リンクするかで扱いが異なるライセンスがある ○ 例: LGPL ● とても難しい話なので詳しいことは省略 ● 興味があればLGPLの全文を読んでください ○ https://www.gnu.org/licenses/lgpl-3.0.html.en 11

Slide 12

Slide 12 text

使い分けは? ● 長短あるので、どっちも使われている ● 好きなのを使えばいい ● 全体的には共有ライブラリのほうが広く使われている(主観) ○ 静的ライブラリを使うよりサイズが圧倒的に小さくて済む ○ ただし、実行ファイルが特定バージョンのライブラリでしか動かないケースを避けるために、実行 ファイルと共有ライブラリを同梱して提供する、本末転倒なケースもある ● コンテナ環境では静的ライブラリによって作られたシングルバイナリが人気 ○ アプリケーションコンテナでは共有ライブラリの利点を活かしにくい 12

Slide 13

Slide 13 text

まとめ ● ライブラリはプログラムのコードをまとめて再利用可能にした塊 ● 静的ライブラリ、共有(動的)ライブラリの二種類がある ● 長短あるので好きなのを使えばよい 13