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() のラッパー関数も提供されていない。 「注意」の節を参照。
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 パラメーターの場合は省略可能である。 配列パラメーターの値はカンマ区切りのリストで指定される。
flags 引数で finit_module() の動作を変更できる。 flags は以下のフラグの 0 個以上の論理和をとって作成したビットマスクである。
そのモジュールがロードされるカーネルに合致することを保証するためのモジュールに組み込みの安全チェックがある。 これらのチェックは、 モジュールの作成時に記録され、 モジュールのロード時に検査される。 最初に、 モジュールはカーネルのバージョン番号と主要な機能 (CPU 種別など) が入った "vermagic" 文字列を記録する。 次に、 モジュールが CONFIG_MODVERSIONS 設定オプションを有効にして作成されている場合、 バージョンハッシュがモジュールが使用するシンボルごとに記録される。 このハッシュはシンボルに対応する関数の引数と返り値の型を基づいて計算される。 この場合、 シンボルのバージョンハッシュは十分に信頼できると考えられているため、 "vermagic" 文字列内のカーネルのバージョン番号は無視される。
MODULE_INIT_IGNORE_VERMAGIC フラグは "vermagic" 文字列を無視することを意味し、 MODULE_INIT_IGNORE_MODVERSIONS フラグはシンボルのバージョンハッシュを無視することを意味する。 カーネルが強制ロードを許可するように作成されている場合 (CONFIG_MODULE_FORCE_LOAD が有効になっている場合)、 モジュールのロードは継続され、 そうでない場合は不正なモジュールに対して返るのと同じエラー ENOEXEC で失敗する。
init_module() では以下のエラーも発生する場合がある。
finit_module() では以下のエラーも発生する場合がある。
上記のエラーに加え、 モジュールの init 関数が実行されてエラーが発生した場合には、 init_module() や finit_module() は失敗し、 errno に init 関数が返した値が設定される。
glibc は finit_module() に対するラッパー関数を提供していない。 syscall(2) を使って呼び出すこと。
現在ロードされているモジュールに関する情報は /proc/modules および /sys/module 以下のモジュール単位のサブディレクトリ内のファイルツリーで参照できる。
Linux カーネルのソースファイル include/linux/module.h には背景に関する有用な情報がある。
#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 以外の全てのポインター要素はモジュール本体内部を指し、 カーネル空間での適切な値で初期化される (つまり、モジュールの残りの 部分で再配置される) ことが期待される。