フック (プログラミング)

フック: hook)は、プログラム中の特定の箇所に、利用者が独自の処理を追加できるようにする仕組みである。また、フックを利用して独自の処理を追加することを「フックする」という。

処理を追加できる箇所は、元のプログラムの開発者によって、あらかじめ決められている。初期化処理や入出力処理などの直前・直後が対象としてよく選ばれる。

主に元のプログラムに対する機能追加・拡張やカスタマイズの手段として使われるほか、デバッグのための情報収集にも有効である。このような有用な使い方の反面、既存のプログラムの動作を変更できることから、悪意を持ったプログラムによって利用される場合もある。例えばOSのキー入力処理のフックを使えばキーロガーを実装できることになる。

また、元のコードそのものは書き換えなくても動作を変更できることから、ROMで提供されるプログラムのバージョンアップや修正に使われることもある。ただしこの場合も、必要な個所に対応するフックがあらかじめ用意されていることが条件となる。すなわち、元のコードを設計する段階から、将来の機能拡張や修正を見越してフックを設計しておく必要がある。

実装例

フック用アドレスが定義されている例

8ビットパソコンのように機械語レベルの単純な制御が行われているシステムでは、フックとして呼出アドレスが定義されている。

例えばMSXの場合、ワークエリアの中に約100個のフック用アドレスが定義され、それぞれタイマ割り込みや各種入出力などに割り当てられている。フックは5バイト間隔で配置されており、初期状態ではRET(Z80におけるサブルーチンからの復帰命令)が書き込まれている。利用者はメモリ上の別の領域に独自の処理を配置し、フック用の5バイトには独自処理へのジャンプ命令を書き込む。

呼出先登録用のAPIが定義されている例

独自処理をプロシージャ関数として定義しておき、登録APIを使って登録する。現代の高級言語によるプログラミングでは、よく見られる実装形態である。

例えばMicrosoft Windowsの場合、OSが提供するフックには整数のIDが振られ、登録用関数SetWindowsHookExが提供されている。フックIDと独自処理への関数ポインタを引数としてSetWindowsHookEx関数を呼び出すと、フック処理として登録される。

フック用変数名や関数名が定義されている例

フックが変数名や関数名で定義されているシステムもある。インタプリタ型のシステムや、コンパイラ型でも利用者が記述した処理と一緒にリンケージエディタにかかる場合(ライブラリが提供するフックのように)などに見られる。

例えばテキストエディタGNU Emacsの場合、Emacs Lispという言語でさまざまな機能が記述されるが、大部分のEmacs Lispパッケージは変数名の末尾が「-hook」となる変数をフックとして定義している。GNU Emacs起動時にはemacs-startup-hookが、c-modeを呼び出した際にはc-mode-hookが評価されるといった具合である。LispプログラムはS式というリストになっており、変数にS式を設定しておけば、変数を評価する際にそのプログラムが実行される。

参考文献

  • ジェイムズ・ノーブル、チャールズ・ウィアー 著、安藤慶一 訳『省メモリプログラミング』(初版)ピアソン・エデュケーション、2002年6月20日(原著2001年)。ISBN 4-89471-408-6 

関連項目