INIT_MODULE(2) | Linux Programmer's Manual | INIT_MODULE(2) |
init_module, finit_module - カーネルモジュールをロードする
int init_module(void *module_image, unsigned long len, const char *param_values); int finit_module(int fd, const char *param_values, int flags);
注意: glibc では、 ヘッダーファイルでの init_module() の宣言はなく、 finit_module() のラッパー関数も提供されていない。 「注意」の節を参照。
init_module() は ELF イメージをカーネル空間にロードし、 必要なシンボルの配置変更を行い、 モジュールパラメーターを呼び出し元から指定された値に初期化し、 最後にそのモジュールの init 関数を実行する。 このシステムコールには特権が必要である。
module_image 引き数はロードするバイナリーイメージが入ったバッファーを指し、 len はバッファーのサイズを指定する。 モジュールイメージは、 実行中のカーネル用に作成された有効な ELF イメージである必要がある。
param_values 引き数はモジュールパラメーター値を指定するスペース区切りの文字列である (モジュールパラメーターは module_param() や module_param_array() を使ってモジュール内で定義される)。 カーネルはこの文字列を解釈し、指定されたパラメーターを初期化する。 各パラメーター指定は以下の形式である。
name[=value[,value...]]
パラメーター name はモジュール内で module_param() を使って定義されているパラメーターのいずれか一つである (Linux カーネルのソースファイル include/linux/moduleparam.h を参照)。 パラメーター value は bool か invbool パラメーターの場合は省略可能である。 配列パラメーターの値はカンマ区切りのリストで指定される。
finit_module() システムコールは init_module() と同様だが、 ファイルディスクリプター fd からモジュールをロードする。 カーネルモジュールの信頼性をファイルシステムにおける場所から判定できる場合、この方法は有効である。 この方法が利用できる場合、 モジュールの信頼性を判定するのに暗号で署名されたモジュールを使用することによるオーバーヘッドを避ける事ができる。 param_values 引き数は init_module() と同じである。
flags 引き数で finit_module() の動作を変更できる。 flags は以下のフラグの 0 個以上の論理和をとって作成したビットマスクである。
そのモジュールがロードされるカーネルに合致することを保証するためのモジュールに組み込みの安全チェックがある。 これらのチェックは、 モジュールの作成時に記録され、 モジュールのロード時に検査される。 最初に、 モジュールはカーネルのバージョン番号と主要な機能 (CPU 種別など) が入った "vermagic" 文字列を記録する。 次に、 モジュールが CONFIG_MODVERSIONS 設定オプションを有効にして作成されている場合、 バージョンハッシュがモジュールが使用するシンボルごとに記録される。 このハッシュはシンボルに対応する関数の引き数と返り値の型を基づいて計算される。 この場合、 シンボルのバージョンハッシュは十分に信頼できると考えられているため、 "vermagic" 文字列内のカーネルのバージョン番号は無視される。
MODULE_INIT_IGNORE_VERMAGIC フラグは "vermagic" 文字列を無視することを意味し、 MODULE_INIT_IGNORE_MODVERSIONS フラグはシンボルのバージョンハッシュを無視することを意味する。 カーネルが強制ロードを許可するように作成されている場合 (CONFIG_MODULE_FORCE_LOAD が有効になっている場合)、 モジュールのロードは継続され、 そうでない場合は不正なモジュールに対して返るのと同じ ENOEXEC で失敗する。
成功の場合、これらのシステムコールは 0 を返す。エラーの場合 -1 が返され、 errno に適切な値が設定される。
init_module() では以下のエラーも発生する場合がある。
finit_module() では以下のエラーも発生する場合がある。
上記のエラーに加え、 モジュールの init 関数が実行されてエラーが発生した場合には、 init_module() や finit_module() は失敗し、 errno に init 関数が返した値が設定される。
finit_module() は Linux 3.8 以降で利用可能である。
init_module() と finit_module() は Linux 固有である。
init_module() システムコールは glibc ではサポートされていない。 glibc ヘッダーでは宣言は提供されていないが、 歴史の紆余曲折を経て glibc はこのシステムコールに対する ABI を公開していない。 したがって、このシステムコールを利用するには、自分のコードの中で手動でインターフェースを宣言すればよい。 syscall(2) を使ってシステムコールを起動できる。
glibc は finit_module() に対するラッパー関数を提供していない。 syscall(2) を使って呼び出すこと。
現在ロードされているモジュールに関する情報は /proc/modules および /sys/module 以下のモジュール単位のサブディレクトリ内のファイルツリーで参照できる。
Linux カーネルのソースファイル include/linux/module.h には背景に関する有用な情報がある。
Linux 2.4 以前では init_module() システムコールはかなり違ったものであった。
#include <linux/module.h>
int init_module(const char *name, struct module *image);
(ユーザー空間アプリケーションは query_module() を呼び出してどのバージョンの init_module() が利用可能かを検出できる。 query_module() の呼び出しは Linux 2.6 以降ではエラー ENOSYS で失敗する。)
古いバージョンのシステムコールは、 image が指す再配置されたモジュールイメージをカーネル空間にロードし、 モジュールの init 関数を実行する。 呼び出し元には再配置されたイメージを提供する責任がある (Linux 2.6 以降では init_module() システムコールが再配置自体を行う)。
モジュールイメージは先頭部分に module 構造体があり、その後ろに 適切なコードとデータが続く。 Linux 2.2 以降では module 構造体は以下のように定義されている。
struct module {
unsigned long size_of_struct;
struct module *next;
const char *name;
unsigned long size;
long usecount;
unsigned long flags;
unsigned int nsyms;
unsigned int ndeps;
struct module_symbol *syms;
struct module_ref *deps;
struct module_ref *refs;
int (*init)(void);
void (*cleanup)(void);
const struct exception_table_entry *ex_table_start;
const struct exception_table_entry *ex_table_end; #ifdef __alpha__
unsigned long gp; #endif };
next と refs 以外の全てのポインター要素はモジュール本体内部を指し、 カーネル空間での適切な値で初期化される (つまり、モジュールの残りの 部分で再配置される) ことが期待される。
create_module(2), delete_module(2), query_module(2), lsmod(8), modprobe(8)
この man ページは Linux man-pages プロジェクトのリリース 3.79 の一部 である。プロジェクトの説明とバグ報告に関する情報は http://www.kernel.org/doc/man-pages/ に書かれている。
2014-05-10 | Linux |