ほぼ何もしない "Hello World" プログラムを作って Linux Kernel に組み込む単純なモジュールの作り方を見ていきます。まだ、デバイスドライバには遠いです。
添付ファイル に一式をまとめておきます。C 言語で実行部を、Makefile で構築手順を書きます。Makefile を書かずにコンパイルできるかというと、自分では試したことがないです。煩雑な記述をした割には得るものが無いでしょう。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | - | | | ! - | ! - | | ! - ! |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | - | | | | | | | | | ! - ! - | |
|
main() はありません。モジュールは Kernel に組み込まれる時 module_init() で指定した関数を実行します。モジュールが Kernel から外されるとき module_exit() で指定した関数を実行します。
モジュールが「組み込まれた」、「外された」時に呼ばれる仕掛けを作ることができるのは分りました。デバイス・ドライバを構成するには足りません。「ハードウエアにドライバが対応するデバイスが追加されたら」、あるいは、「モジュールが組み込まれた時点で既にドライバが対応するハードウエアが存在したら」、呼び出される様な仕掛けをまだ作っていません。
printk は printf に相当する関数です。書式文字列を指定して書式文字列に続く引数の内容を表示します。書式文字列は printf とよく似ています。興味深く注意が必要な拡張は %p とその派生書式です。ここでは printk のヘッダファイル読み込みに linux/kernel.h を使用しました。もちろん、linux/printk.h を直接インクルードするのも良いでしょう。
printk に浮動小数点形式の書式が無いようだが...
printkの書式に浮動小数点形式はありません。kernel の中では double, float とその派生型は使えません。自分は実施したことが無いのですが、浮動小数点レジスタの値とこれに関係するコンテキストを保存・復帰すれば使えるはずです。ただし、処理の出入り口に実装する程度の簡単なことではなく、suspend/resume、コンテキスト・スイッチ、プロセッサ active/idle の状況などを細かに意識する必要が有ります。実装に問題があるとアプリケーションで行っている計算結果が不意にとんでもない値になるなど問題追跡が難しい状況に陥ります。
関数に __init と __exit 修飾子がついています。 include/linux/init.h を読んでみると、広域変数に対して似たようなマクロ定義があることが判ります。__init と __exit 修飾子の目的は 次のようになります。
__init と __exit は Kernel のメモリ使用量をなるべく減らすために使われる修飾子です。
KERN_INFO は kernel message の表示レベルを意味します。include/linux/kern_levels.h には次のレベルが定義されています。おそらく普通に使うのは KERN_ERR より大きい Level 番号のメッセージでしょう。
Macro | Level | alternate function | alternate function for device driver | Description |
KERN_EMERG | 0 | pr_emerg | dev_emerg | system is unusable |
KERN_ALERT | 1 | pr_alert | dev_alert | action must be taken immediately |
KERN_CRIT | 2 | pr_crit | dev_crit | critical conditions |
KERN_ERR | 3 | pr_err | dev_err | error conditions |
KERN_WARNING | 4 | pr_warn, pr_warning | dev_warn | warning conditions |
KERN_NOTICE | 5 | pr_notice | dev_notice | normal but significant condition |
KERN_INFO | 6 | pr_info | dev_info | informational |
KERN_DEBUG | 7 | pr_debug, pr_devel | dev_dbg | debug-level messages pr_debug, pr_devel, dev_dbg は DEBUG, CONFIG_DYNAMIC_DEBUG マクロにより、実装したコードそのものが削除されたり、動的に制御される対象になります。リンク先を参照して条件を確認してください。 |
KERN_XXX は行の先頭で有効です
KERN_XXX は行の先頭にあるものが有効です。printk を何回か使い、行を分割して出力した場合に、途中に KERN_XXX を入れても効果がありません。途中に誤って入れても、致命的な問題は起こしません。表示やログファイルの内容が乱れるだけです。
/proc/sys/kernel/printk リンク先の printk 節を参照 にログレベルを書き込むことで console と ログファイル(厳密にはログ出力ノード /proc/kmsg) に出力するレベルを制御できます。説明の中で "Higher" とあるのは上記表 Level においてより小さい値です。