ほとんどの一般的なアプリケーションは共有ライブラリを使用します。 これらの共有ライブラリは起動時にメモリーに読み込まれる必要があります。 また各種シンボルの参照が解決される必要があります。 多くの小さなプログラムにとってこのダイナミックリンクはとても素早く行われます。 しかしC++で書かれたプログラムやたくさんのライブラリに依存するプログラムにとってダイナミックリンクはかなりの時間がかかります。
大部分のシステムでは、ライブラリはそんなに変更されることがありません。そしてプログラムが起動されるときにリンクされるプログラムは毎回同じです。prelinkはlink情報を取り出し、それを実行ファイルに格納します。つまりprelinkを行ないます。リンカーのためにglibc内のld-linux.soが必要です。
prelinkはアプリケーションの起動時間を短縮できます。例えば、典型的なKDEプログラムの起動時間は50%も短縮することができます。prelinkの唯一必要なメンテナンスは、ライブラリをアップグレードしたときに毎回prelinkしている実行ファイルを再度prelinkすることです。
警告: prelinkはHardened Gentooでは動作しないでしょう。これは、 両プロジェクトが共有ライブラリにおけるアドレススペースのマッピングを変更しようとしているためです。 しかし、prelinkを-Rオプションで使用すると、 ライブラリのベースアドレスをランダム化しある程度防御を高めてくれます。 |
最初にprelinkツールをインストールする必要があります。このemergeプロセスは自動的に、このマシンがprelinkを安全にできるか確認します。
コード表示 2.1: prelinkのインストール |
# emerge prelink
|
多くの人がprelinkのemergeで確認テストエラーがでます。そのテストはいくつかの安全性のために行われています。それらを無効にすると、prelinkはどうなるかわかりません。そのemergeエラーは通常binutils,gcc,glibcといったcoreパッケージに依存しています。それらのパッケージをその順番で再度emergeしてみてください。
注意: Tip: もしエラーが出たら、あなた自身でprelinkのコンパイル、テスト(./configure ; make ; make check)を行ってみてください。するとエラー時に、testsuiteディレクトリに*.logファイルが作成されます。そのファイルにはいくつかの役立つ手掛りが載っています。 |
他のシステム(マシン)で再びエラーがおきる場合には、Bugzillaをチェックし、 まだレポートされていない場合にはバグレポートを作成して下さい。
また、CFLAGS/CXXFLAGSに-fPICが入っていないことを確認してください。 もし設定されている場合には、システム全体を-fPICなしで再構築する必要があります。
env-updateを実行することで"/etc/prelink.conf"ファイルが作成されます。このファイルはどのファイルをprelinkするかが記述されています。
コード表示 2.2: env-updateの実行 |
# env-update
|
残念ながら古いバージョンのbinutilsをよってコンパイルされていたファイルはprelinkできません。これらのアプリケーションの大部分は/optにインストールされているバイナリのみのパッケージです。次のファイルを記述することによってそれらをprelinkしないようにします。
コード表示 2.3: /etc/env.d/60prelink |
PRELINK_PATH_MASK="/opt" |
注意: コロンで区切って複数のディレクトリを記述することができます。 |
/etc/prelink.confによって与えられたディレクトリのバイナリすべてをprelinkするために以下のコマンドが使えます。
コード表示 3.1: listされたファイルのprelink |
# prelink -amR
|
警告: ディスクの残りスペースが少ないときには、バイナリの一部分が切り捨てられてしまう場合があります。この結果システムが壊れてしまいます。"file"や"readelf"コマンドを使ってバイナリファイルの状態をチェックしてください。または、df -hコマンドを仕様してハードディスクの空き容量をチェックしてください。 |
| オプションの説明 | |
| -a | "All": すべてのバイナリをprelinkする。 |
| -m | 仮想メモリ空間を確保します。prelinkするライブラリが多い場合に必要です。 |
| -R | アドレスの順序をランダムにします。これはbuffer overflowに対してのセキュリティが増大します。 |
注意: 他のオプションや詳細はman prelinkを見てください。 |
sys-devel/prelink-20060213以降であれば、 cronジョブを/etc/cron.daily/prelinkにインストールします。 有効にするには、設定ファイル/etc/conf.d/prelinkを編集します。 これによりprelinkが毎日バックグラウンドで実行され、必要に応じコマンドを手動で実行する手間がなくなります。
KDEの読み込み時間をprelinkした後で大幅に減少させることができます。 KDEにprelinkされていることを通知すると、KDEはkdeinitの実行をしなくなり(必要ないので)、さらにスピードアップします。
/etc/env.d/*kdepaths*にKDE_IS_PRELINKED="true"を記述して、 KDEにprelinkのことを教えてあげてください。
prelinkをしたくなくなったならば、prelinkをアンインストールする前に、 先に/etc/cron.dailyと/etc/conf.d/prelinkにあるprelinkのcronjobを削除しなくてはなりません。 次に、以下のようにしてすべてのバイナリからprelinkを取り除かなくてはなりません。
コード表示 3.2: すべてのバイナリからのprelinkの除去 |
# prelink -au
|
最後に、以下のようにしてprelinkパッケージそのものをアンインストールします。
コード表示 3.3: prelinkのアンインストール |
# emerge -aC prelink
|
この問題の原因は、gccのオプション-fPICなしでobjectファイルをコンパイルされた共有ライブラリにあります。
以下は、まだ修正が終わっていないか修正できないライブラリです。
このリストに載っていない問題のあるライブラリがある場合には、できれば-fPICを関連するCFLAGSに追加したパッチと一緒に連絡してください。
システムをprelinkしたらいくつかのスタティックバイナリが動かなくなりました。
glibcが関係しているところでは、100% スタティックバイナリのことはありません。glibcと静的にコンパイルした場合には、他のシステムに依存していることになります。以下はDick Howellによる説明です。
"ダウンロードしたバイナリパッケージはすべてを自分自身に含んでいるため、ターゲットシステムのローカルライブラリに依存しないと考えます。しかしあいにくLinux、また他のGLIBCを使用したシステムで、これは完全に真ではありません。さまざまなデータベースへの認証、ネットワーク情報などの機能を提供する"libnss"(ネームサービススイッチライブラリ。 ネットワークセキュリティシステムと呼ばれることもある)があります。これはそのマシンの実際のネットワークに依存しないアプリケーションプログラムを作ることができます。良い考えですが、GLIBCを変更するとロードするときに問題が置こる場合があります。"libnss"をスタティックリンクすることはできません。なぜならそれぞれのマシン個々で設定されているからです。その問題は主に他のGLIBCライブラリと静的にリンクれている場合に起こると考えます。特に"libnss"から個々に呼ばれる"libpthread"、"libm"、"libc"で起こります。"
Prelinkが"prelink: dso.c:306: fdopen_dso: Assertion `j == k' failed."のメッセージを出して異常終了しました。
これは良く知られた問題です。ここで、親切に解説されています。 prelinkはUPX圧縮された実行形式を処理することができません。 prelink-20021213の時点で、prelinkの最中にそのファイルを隠しておくことしか、解決する方法はありません。ファイルを隠す簡単な方法がprelinkの設定にあるので見てください。
grsecurityを使用しているのですが、prelinkが動かないようです。
randomized mmap() baseを使用するgrsecurityを使用したシステム上でprelinkを行なうためには、 /lib/ld-2.3.*.soに関して"randomized mmap() base"をオフにする必要があります。 これはchpaxユーティリティによって行なうことができますが、 ファイルが使用中でないときに行なう必要があります(rescue CDを使用してbootするなどします)。
prelinkが"prelink: Can't walk directory tree XXXX: Too many levels of symbolic links"のエラーを出して失敗しました。
シンボリックリンクが深くネストされすぎています。これはシンボリックリンクが自身をポイントしている場合に発生します。 例えば、/usr/lib/lib -> libが最も一般的です。これを修正するには、 そのシンボリックリンクを手動で見つけるか、またはsymlinksパッケージで提供されているユーティリティを使用します。
コード表示 4.1: シンボリックリンクの修正 |
# emerge symlinks # symlinks -drv / |
より詳細な情報は、 Bugzillaやこのフォーラムの投稿で見つかります。
prelinkは多くの巨大なアプリケーションの起動時間を短縮することができます。そしてPortageでサポートされています。prelinkはまたもし問題に直面した場合には安全にいつでもどのバイナリでも元に戻すことができます。ただ一つ次のことを覚えておいてください。prelinkを使用したglibcや他のライブラリをアップデートしたときには、prelinkを再度実行する必要があります。まあ、つまり、がんばってね!
このドキュメントの内容は Creative Commons - Attribution / Share Alikeライセンスです。