Linux デバイスドライバ -よりプログラムらしく-
投稿日: | |
---|---|
タグ: |
目次
本稿は「Linux デバイスドライバ -Hello-」の続きであり,よりプログラムらしいプログラムを作るためのコードをいくつか紹介する.
タグ
関数やオブジェクトはタグを付けることで特殊な扱いを受ける.以下にその例をいくつか示す.
- __init
- この宣言を行った関数は初期化時のみメモリを使用し,すぐに解放する.例を以下に示す.
static int __init hello_init(void) { printk(KERN_ALERT "Hello, World\n"); return 0; }
- __initdata
- この宣言を行ったオブジェクトは__initでのみ使用されることを表す.
- __exit
- クリーンアップ用の関数であることを指定する.コンパイラはこの宣言が行われた関数を特殊なセクションに配置する.
static void __exit hello_init(void) { printk(KERN_ALERT "Goodbye, World\n"); return 0; }
- __exitdata
- この宣言を行ったオブジェクトは__exitでのみ使用されることを表す.
モジュール引数
パラメータの値はロード時にinsmodかmodprobeによって割り当てられる.modprobeは設定ファイルからパラメータを読み込むことが可能.設定ファイルの名前は,/etc/modprobe.confや/etc/modprobe.d/内の拡張子.confのファイルである.マニュアル"man modprobe.conf"でフォーマットについて確認ができる.
パラメータの取得は,<linux/moduleparam.h>で定義される関数module_paramやmodule_param_arrayで行う.この関数もまたmodule_initらと同様関数の外で使用しないとエラーである.
- module_param(variable, type, perm)
-
- variable
- 代入する変数名を指定する.
- type
-
型を指定する.指定可能な型は次の通り.
bool 論理値 invbool boolの逆の値 charp 文字列へのポインタ値. short 整数値 符号付き int long ushort 符号なし uint ulong - perm
- パーミッション値.誰がsysfsに現れるモジュールパラメータにアクセスできるかを制御する.この引数には<linux/stat.h>にある定義を使用する.例えば,"S_IRUGO|S_IWUSR"はルートがパラメータを変更することを許可する.
コンパイルは依然の記事の通り.以下がコンパイルと実行結果である.#include <linux/init.h> #include <linux/module.h> #include <linux/moduleparam.h> #include <linux/stat.h> static int i; module_param(i, int, S_IRUGO); static int __init init() { printk(KERN_INFO "i=%d\n", i); return 0; } static void __exit fini(){} module_init(init); module_exit(fini);
user% make -C ./linux-3.0.9 M=$PWD modules user% sudo insmod param.ko i=100 array={1,2,3,4,5} user% dmesg | tail -1 [41654.053664] name:insmod pid:27744 user% sudo rmmod param.ko
- module_param_array(variable, type, num, perm)
-
モジュールが引数として配列を与えられた時にそれを取得する.variableには配列を記述する.
- num
- 変数の数を指定する.
カレントプロセス
カーネルモジュールの処理はアプリケーションと異なり,順に実行される訳ではなく,個々のプロセスに関連付けられる.現在のプロセスに関する情報は,<asm/current.h>で定義されているcurrentによって取得できる.currentは<linux/sched.h>で定義されるstruct task_struct型へのポインタである.
#include <linux/init.h>
#include <linux/module.h>
#incldue <asm/current.h>
#incldue <linux/sched.h>
MODULE_LICENSE("Dual BSD/GPL")
static void info_proc(void)
{
printk(KERN_INFO "name:%s pid:%i",
current->comm, current->pid);
}
static int __init init(void){ info_proc(); return 0; }
static void __exit fini(void){ info_proc(); }
module_init(init);
module_exit(fini);
エラー
Linuxカーネルのエラーコードは負数で,<linux/errno.h>で定義されている.例えば定数ENOMEMに関連付けたエラーを表す場合,関数は-ENOMEMを返す.