Presentation is loading. Please wait.

Presentation is loading. Please wait.

組込みエンジニアのためのLinux入門 ダイナミックリンク編(3)

Similar presentations


Presentation on theme: "組込みエンジニアのためのLinux入門 ダイナミックリンク編(3)"— Presentation transcript:

1 組込みエンジニアのためのLinux入門 ダイナミックリンク編(3)
株式会社アプリックス 小林哲之

2 このスライドの対象とする方 今までずっと組込み機器のプロジェクトに携わってきて最近はOSにLinuxを使っている方々

3 このスライドの目的 Linuxで使用されているダイナミックリンクの仕組みを理解し現在のプロジェクトに役立てる。
仕組みを知らなくてもプログラムは動くが、トラブルに対処したり性能を引き出すためには仕組みの理解が重要。

4 今日のお題 共有ライブラリの簡単な歴史 Prelinkとは Prelinkのtips

5 共有ライブラリの簡単な歴史 a.out時代 ELF時代 ELF + prelink

6 a.out 時代 a.outはLinuxの最初のオブジェクトフォーマット。 共有ライブラリのリンクは静的に行う。
ライブラリの配置アドレスは人手によって管理されていた。 ライブラリの更新でサイズが変わると大変。 世の中の全てのライブラリを重ならないように配置しようとするとアドレス空間が足りなくなる! ライブラリの作成も大変。 起動時の処理はシンプルなので速い。

7 ELF時代 ELFはダイナミックリンクが簡単にできるように考慮されたオブジェクトフォーマット ダイナミックリンク
ライブラリの配置アドレスは起動時に決定 ライブラリのアドレスの集中管理が不要になった ライブラリの作成も簡単になった 起動時にリンクを行う 起動時のオーバーヘッドが大きくなった

8 ELF + prelink a.out ELF ELF + prelink 大変 ラク 小 大
ライブラリの作成、管理 大変 ラク 起動時のオーバーヘッド PrelinkはELFのライブラリの作成、管理の容易さを保ったまま 起動時のオーバーヘッド削減を目指す

9 Prelinkとは 通常は起動時に行われるリンクの処理を、 あらかじめ済ませておくことにより起動時間の短縮をねらう。
CELFテクニカルジャンボリーでもたびたび紹介され、起動時間短縮の効果が実証されている。

10 CELFでのprelinkの紹介 テクニカルジャンボリー #3 (2005.7) テクニカルジャンボリー#9 (2006.7)
“携帯電話にLinuxを実装する!”  シンボルの解決にかかる時間が2479msec →125msec テクニカルジャンボリー#9 (2006.7) “NECによる携帯電話向けリナックスの改良” テクニカルジャンボリー #13 (2007.2) “Evaluation of MIPS pre-link” Prelinkのまとめページ

11 Prelinkは実際に何をやってくれるのか
ダイナミックリンクライブラリは起動時に配置アドレスが決まるので、その後のシンボルの解決等のローダの処理の負荷が大きかった。 Prelinkでは 全てのダイナミックリンクライブラリを走査して配置するアドレスを決定する。 それぞれのダイナミックリンクライブラリのロードアドレスを決定したアドレスにセットする. 依存関係のある実行ファイル、ダイナミックリンクライブラリのアドレス参照を解決する。 これによりローダの起動時の処理が大幅に軽減された。

12 prelinkの使用法 $ prelink -avR
-a /etc/prelink.conf に指定してあるディレクトリのダイナミックリンクライブラリと 実行ファイルのprelinkを行う -v vorbose -R アドレスをランダムに決める (ウィルス耐性が高まる) $ prelink <filename> 追加で指定されたファイルのprelinkを行う

13 /etc/prelink.cache 各ライブラリのアドレスと依存関係がバイナリフォーマットで格納される。
prelink –p で確認することができる。 # prelink -p 152 objects found in prelink cache `/etc/prelink.cache' /usr/lib/libwwwfile.so [0x41eeda3e] 0x4a x4a597dec: /lib/tls/libdl so [0x536dae10] /lib/tls/libc so [0xedb6e392] /lib/ld so [0x040c82cc] /usr/lib/libsctp.so [0x26ac5ae2] 0x4adc8000-0x4add12ac: /usr/lib/libreadline.so.4.3.old [0xf90fc4bc] 0x x4144b770: /usr/lib/libwwwnews.so [0xdc63747e] 0x4ac x4ac86310: ....

14 通常のライブラリ ロードアドレスが0 $ readelf -l libc-2.3.3.so
Elf file type is DYN (Shared object file) Entry point 0x13708 There are 11 program headers, starting at offset 52 Program Headers: Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align EXIDX x0fbc3c 0x000fbc3c 0x000fbc3c 0x x01310 R 0x4 PHDR x x x x x00160 R E 0x4 INTERP x0fb410 0x000fb410 0x000fb410 0x x00014 R 0x4 [Requesting program interpreter: /lib/ld-linux.so.3] LOAD x x x xfcf78 0xfcf78 R E 0x8000 LOAD x0fda64 0x00105a64 0x00105a64 0x x04da8 RW 0x8000 DYNAMIC x0fef1c 0x00106f1c 0x00106f1c 0x000e0 0x000e0 RW 0x4 NOTE x x x x x00020 R 0x4 NOTE x0fdafc 0x00105afc 0x00105afc 0x x00074 R 0x4 TLS x0fdae0 0x00105ae0 0x00105ae0 0x x00028 R 0x4 GNU_EH_FRAME 0x0fcf4c 0x000fcf4c 0x000fcf4c 0x0002c 0x0002c R 0x4 GNU_RELRO x0fda64 0x00105a64 0x00105a64 0x0159c 0x0159c R 0x1 ロードアドレスが0

15 prelinkしたライブラリ ロードアドレスが 割り当てられている $ readelf -l libc-2.3.3.so
Elf file type is DYN (Shared object file) Entry point 0x491c3708 There are 11 program headers, starting at offset 52 Program Headers: Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align EXIDX x0fbc3c 0x492abc3c 0x492abc3c 0x x01310 R 0x4 PHDR x x491b0034 0x491b0034 0x x00160 R E 0x4 INTERP x0fb410 0x492ab410 0x492ab410 0x x00014 R 0x4 [Requesting program interpreter: /lib/ld-linux.so.3] LOAD x x491b0000 0x491b0000 0xfcf78 0xfcf78 R E 0x8000 LOAD x0fda64 0x492b5a64 0x492b5a64 0x x04da8 RW 0x8000 DYNAMIC x0fef1c 0x492b6f1c 0x492b6f1c 0x000e0 0x000e0 RW 0x4 NOTE x x491b0194 0x491b0194 0x x00020 R 0x4 NOTE x0fdafc 0x492b5afc 0x492b5afc 0x x00074 R 0x4 TLS x0fdae0 0x492b5ae0 0x492b5ae0 0x x00028 R 0x4 GNU_EH_FRAME 0x0fcf4c 0x492acf4c 0x492acf4c 0x0002c 0x0002c R 0x4 GNU_RELRO x0fda64 0x492b5a64 0x492b5a64 0x0159c 0x0159c R 0x1 ロードアドレスが 割り当てられている

16 prelinkしたライブラリ この3つのセクションが追加された。 その分だけファイルサイズ増加。
# objdump -h libc so libc so: file format elf32-littlearm Sections: Idx Name Size VMA LMA File off Algn 0 .note.ABI-tag b b **2 CONTENTS, ALLOC, LOAD, READONLY, DATA, LINK_ONCE_SAME_CONTENTS 1 .hash e b01b4 491b01b b4 2**2 CONTENTS, ALLOC, LOAD, READONLY, DATA ... 69 .gnu_debuglink f4 2**2 CONTENTS, READONLY 70 .gnu.liblist c 2**2 71 .gnu.libstr **0 72 .gnu.prelink_undo 00000cac **2 # この3つのセクションが追加された。 その分だけファイルサイズ増加。

17 Prelinkによるファイルサイズの増加
size(bytes) prelinked size(bytes) delta delta% libc.so 1,054,936 1,058,384 3,448 libm.so 432,088 433,792 1,704 libcrypt.so 27,556 29,429 1,873 libdl.so 15,036 16,900 1,864 libX11.so 769,468 770,988 1,520 libglib-2.0.so 557,908 559,508 1,600 libgtk-x so 2,846,996 2,849,320 2,324 bash 615,940 645,220 29,280 busybox 622,640 627,596 4,956 init 28,356 31,356 3,000 数KBの増加。

18 実行時のローダの動きを比較してみる 環境変数 LD_DEBUG=all で実行すると ローダの実行ログが表示される。
それをファイルに保存するためには LD_DEBUG_OUTPUT=<file name> 統計情報のみ欲しい場合は LD_DEBUG=statistics

19 LD_DEBUG=allの例 この例では全部で38000行 # LD_DEBUG=all ./gtk_hello .......
559: symbol=malloc; lookup in file=./gtk_hello 559: symbol=malloc; lookup in file=/usr/lib/libgtk-x so.0 559: symbol=malloc; lookup in file=/usr/lib/libgdk-x so.0 559: symbol=malloc; lookup in file=/usr/lib/libXrandr.so.2 559: symbol=malloc; lookup in file=/usr/lib/libXfixes.so.3 559: symbol=malloc; lookup in file=/usr/lib/libXcursor.so.1 559: symbol=malloc; lookup in file=/usr/lib/libatk-1.0.so.0 559: symbol=malloc; lookup in file=/usr/lib/libgdk_pixbuf-2.0.so.0 559: symbol=malloc; lookup in file=/usr/lib/libpangoxft-1.0.so.0 559: symbol=malloc; lookup in file=/usr/lib/libXft.so.2 559: symbol=malloc; lookup in file=/usr/lib/libXrender.so.1 559: symbol=malloc; lookup in file=/usr/lib/libXext.so.6 559: symbol=malloc; lookup in file=/usr/lib/libfontconfig.so.1 559: symbol=malloc; lookup in file=/usr/lib/libfreetype.so.6 559: symbol=malloc; lookup in file=/usr/lib/libz.so.1 559: symbol=malloc; lookup in file=/usr/lib/libpangox-1.0.so.0 559: symbol=malloc; lookup in file=/usr/lib/libX11.so.6 559: symbol=malloc; lookup in file=/usr/lib/libpango-1.0.so.0 559: symbol=malloc; lookup in file=/lib/tls/libm.so.6 559: symbol=malloc; lookup in file=/usr/lib/libgobject-2.0.so.0 559: symbol=malloc; lookup in file=/usr/lib/libgmodule-2.0.so.0 559: symbol=malloc; lookup in file=/lib/tls/libdl.so.2 559: symbol=malloc; lookup in file=/usr/lib/libglib-2.0.so.0 559: symbol=malloc; lookup in file=/lib/tls/libc.so.6 559: binding file /usr/lib/libexpat.so.0 to /lib/tls/libc.so.6: normal symbol `malloc' [GLIBC_2.4] この例では全部で38000行

20 LD_DEBUG=statisticsの例
# LD_DEBUG=statistics ./gtk-hello 574: number of relocations: 547 574: number of relocations from cache: 44 574: number of relative relocations: 14309 574: 574: runtime linker statistics: 574: final number of relocations: 1957 574: final number of relocations from cache: 44 プロセスID

21 Prelinkの効果 547 44 33 14309 1957 56 prelink無し libのみprelink 全て prelink
number of relocations 547 number of relocations from cache 44 33 number of relative relocations 14309 runtime final number of relocations 1957 56 final number of relocations from cache テストプログラムは gtkで画面上にボタンを1個表示するもの。

22 実行時の物理メモリ消費量の比較 4300 4216 4164 prelink無し libのみprelink 全て prelink
VmRSS (KBytes) 4300 4216 4164 -136KB テストプログラムは前頁と同じもの。 cat /proc/PID/status で観測した。 起動時のrelocationの処理が軽くなったのに伴って物理メモリ使用量も 減少している。

23 簡単なまとめ プラス面 マイナス面 起動時間が短縮される 実行時の物理メモリ消費量も少なくて済む ルートファイルシステム構築時に1工程増える
ファイルサイズが少し増加する 大抵のケースではプラス面が勝るであろう。

24 Prelinkの柔軟性 prelinkされていないライブラリが混じってしまっても起動時間は最適でないけれども実行はできる。このため致命的な問題が起こりにくい。 prelinkしたライブラリを元に戻すこともできる。(undoのための情報を保持している。この情報の削除に関して後述)

25 PrelinkのTips stripしてからprelinkするほうがファイルサイズが小さくなる。
undo情報を削除してファイルサイズを減らそうと試みた(しかしうまくいかなかった。)

26 ビルド手順へのprelinkの組込み stripしてからprelinkするほうがファイルサイズが小さくなる。
size: 6,508 size: 9,452 strip 元の実行ファイル こちらが小さい size: 10,511 strip size: 13,699 size: 9,692 prelink 先にstripしたほうが、prelinkのときに付加されるundoのための情報の サイズが小さくて済むため

27 undo情報を削除してファイルサイズを減らす
undo情報は起動時には使用されることが無い。組込みの場合はundoすることはあまりないと思われるため、undo情報は冗長? objcopyコマンドかstripコマンドでundo情報のセクションを削除する $ strip –remove-section=.gnu.prelink_undo <filename> これで減らせるファイルサイズは数百バイト~数キロバイト PCのLinux環境では問題がなかったが、手元にあったARMの環境では 実行ファイルでこれを行うと起動時にsegmentation faultになるものがあった。 ライブラリだけなら問題なかった。

28 参考文献 “Prelink” http://people.redhat.com/jakub/prelink/prelink.pdf
“Linkers & Loaders” オーム社 “BINARY HACKS” オライリージャパン “GNU Development Tools” Wataru Nishida GNU C ライブラリのソース その他たくさんのWEB検索結果


Download ppt "組込みエンジニアのためのLinux入門 ダイナミックリンク編(3)"

Similar presentations


Ads by Google