Presentation is loading. Please wait.

Presentation is loading. Please wait.

Linux Device Driver 輪講 2. モジュールの作成と実行

Similar presentations


Presentation on theme: "Linux Device Driver 輪講 2. モジュールの作成と実行"— Presentation transcript:

1 Linux Device Driver 輪講 2. モジュールの作成と実行
ACE suzuk

2 table of contents テスト用システムのセットアップ Hello Worldモジュール モジュール対アプリケーション
コンパイルとロード カーネルシンボルテーブル 準備情報 初期化とシャットダウン モジュールパラメータ ユーザ空間を使う

3 1.テスト用システムのセットアップ Linuxドライバ実装&テスト環境を構築 2.6からはシステム上にカーネルツリーが必要
kernel.orgから2.6カーネルソースをDLし、/usr/src以下にインストールする 実行カーネルと同じバージョンのカーネルソースをインストールするのが望ましい

4 2.Hello Worldモジュール 2つの関数に注目 printk module_init (カーネルマクロ)
モジュールのカーネルにロード時に実行 module_exit (カーネルマクロ) モジュールのカーネルからの削除時に実行 printk Cライブラリなしに実行するためのprintfに似た関数 モジュールがprintkを呼び出せるのはなぜ?  insmodでロードするとモジュールがカーネルにリンクされ、 カーネルのパブリックシンボルにアクセスできるようになるため

5 printkについてもう少し・・・ i.e. printk(KERN_ALERM “hello\n”); KERN_ALERM
メッセージの重要度

6 3.モジュール対アプリケーション カーネルモジュールは全てイベントドリブン モジュールはカーネルだけにリンクされる カーネルヘッダ
終了関数は初期化関数で作成したオブジェクトを全て注意深く消去する必要がある システムリブートまで資源を解放できなくなるため モジュールはカーネルだけにリンクされる 呼び出せる関数はカーネルがエクスポートしたもの リンクすべきライブラリがない! 通常のヘッダファイルをインクルードしてはだめ! ライブラリがリンクされないため(stdarg.hはOK) カーネルヘッダ include/linux, include/asm カーネルサブシステムヘッダ 上記ディレクトリ以外のサブディレクトリ カーネルモジュールの深刻なエラーはシステム全体を巻き込む

7 カーネルモジュールの役目 カーネルの機能を拡張すること システムコールの一部として実行される 割り込み処理を担当する
カーネル空間で実行される

8 ユーザ空間とカーネル空間 カーネルモードとユーザモード 異なるCPUのランレベルを利用する
セキュリティと安全性のため異なる特権状態で命令を実行する 異なるCPUのランレベルを利用する Linuxでは特権モードと非特権モードの2つを使い分ける

9 カーネルモード あらゆるハードウェア資源にアクセス可能 オペレーティングシステムの実行モード プロセス プロセス プロセス ユーザモード
システムコール カーネル カーネルモード デバイス

10 ユーザモード ハードウェア資源へのアクセスを制限・監視下でプログラムを実行 通常のプログラムの実行モード プロセス プロセス プロセス
システムコール カーネル カーネルモード デバイス

11 CPUのランレベル 多くのCPUは2つ以上の実行モードを保有 実行レベルを使い分けることで安全性、安定性を向上させる
Intel 80x86は4つの実行リング(特権の階層)を持つ ランレベル0をカーネルモード それ以上をユーザモードに割り当てる

12 カーネル内の並行処理 常に並行処理を意識した実装が必要 複数プロセスがドライバを同時に使用した時 デバイスの非同期の割り込み実行
ソフトウェア割り込み実行 カーネルタイマ(7章) マルチプロセッサ プリエンプティブ対応のリエントラントな実装 同時に複数のコンテキストで実行できなくてはだめ 共有データの安全性 競争状態の回避(実行順序の依存性をなくす)

13 カレントプロセス カーネルモジュールは、順々に実行されない カーネルの多くのアクションは個々のプロセスに関連付けられる
ユーザプロセスと違う! カーネルの多くのアクションは個々のプロセスに関連付けられる currentグローバル変数でカレントプロセス情報を利用する asm/current.h, linux/sched.hを参照のこと linux/sched.hをincludeして参照できる printk(KERN_INFO “process is %s (pid:%i)\n”, current->comm, current->pid);

14 カーネルの海路に旅立つあなたへ 心に留めておくべき事柄 カーネルのスタックは非常に小さく、スタックを共有する必要がある
大きな自動変数は良くない! 大きな構造体の場合動的割り当てにする __(ダブルアンダースコア)関数の使用に注意 インタフェースの下位レベルコンポーネント 浮動小数点の計算ができない

15 4.コンパイルとロード カーネルソースはコンパイラに関して非常に多くの仮定を持つ(コンパイラ依存)
Documentation/Changesに必要ツールとバージョンのリスト 全てを知りたい Documentation/kbuild以下を読む

16 モジュールのロードと削除 insmod (モジュールのロード) modprobe rmmod モジュールコードとデータをカーネルにロード
モジュール内の未解決シンボルをカーネルのシンボルテーブルとリンクする ファイルでなくメモリイメージを修正する点がリンカと違う 全てを知りたい人kernel/module.cを参照! sys_init_module(systemcallには先頭がsys_) modprobe 他のモジュール依存を解決してからロード rmmod モジュールをカーネルから削除

17 helloworldのコンパイルとロード
Makefile obj-m := helloworld.o コンパイル make -C /usr/src/linux M=`pwd` modules ロードと削除 insmod ./helloworld.ko rmmod ./helloworld.ko 結果 /var/log/messages May 3 05:07:48 localhost kernel: Hello, world May 3 05:07:58 localhost kernel: Goodby, cruel world Makefileはサンプルを参照のこと

18 カーネルのバージョンへの依存性 カーネルのバージョンが変わるたびに再コンパイルする必要がある 複数バージョンに対応するには
モジュールから見たカーネルインタフェースはバージョン毎にかなり変更される 複数バージョンに対応するには #ifdefとマクロを活用する

19 5.カーネルシンボルテーブル グローバルなカーネルアイテムのアドレステーブル
関数や変数のテーブル ロードされたモジュールのエクスポートされたシンボルは全てカーネルシンボルテーブルに追加される 通常はエクスポートする必要はない モジュールを積み重ねる(stack)こともできる USB入力デバイスモジュールはusbcoreとinputモジュールに積み重ねられる スタックされたモジュールにはmodprobeが便利 インストール済みモジュールだけ探索することに注意

20 5.カーネルシンボルテーブル 2 シンボルをエクスポート 宣言 モジュールのELFセクションにストアされる
5.カーネルシンボルテーブル 2 シンボルをエクスポート 宣言 EXPORT_SYMBOL(name); EXPORT_SYMBOL_GPL(name); モジュールのELFセクションにストアされる 全てを知りたい人はlinux/module.h 下位レベル のデバイス操作 parport_pc カーネルAPI (メッセージ出力、 ドライバ登録、 ポート割り当てなど) ポートの共有と デバイスの登録 parport lp ※パラレルポートドライバvモジュールのスタックの様子

21 6.準備情報 全てのモジュールで必要なヘッダ その他のヘッダ ライセンス指定 linux/module.h linux/init.h
シンボルと関数の定義 linux/init.h 初期化とクリーンアップの関数指定 その他のヘッダ moduleparam.h モジュールロードにおけるパラメータ指定 ライセンス指定 MODULE_LICENSE(“GPL”); マクロで! フリーライセンス指定しないとロード時にカーネルが汚染されたと表示される

22 7.初期化とシャットダウン module_init(initfunc_name) module_exit(cleanupfunc_name)
__initdataタグ 初期化の間だけ使用されるデータ module_exit(cleanupfunc_name) __exit cleanupfunc_name __exitはクリーンアップの際に使用されるものと宣言 facilityの登録 モジュールは多くの異なるfacilityを登録できる 装備には、facilityごとに特定の登録カーネル関数がある

23 初期化関数におけるエラー処理 常に戻り値をチェックしたエラー処理が必要 モジュールロードを継続できない場合は、そこまでの登録を取り消す
エラー処理にはgoto文が有効

24 モジュールロード時の競争 facilityをサポートする内部の初期化手続きが完了するまで、そのfacilityを登録しない
初期化関数の実行が終了しない状態で、カーネルがモジュールを呼び出す可能性がある 初期化が決してエラーにならないようにする

25 8.モジュールパラメータ ロード時にinsmodかmodprobeで指定できる
modprobeは/etc/modprobe.confからパラメータを読み取る module_param, module_param_arrayマクロを使う(moduleparam.hで定義) static char *whom = “world”; static int howmany = 1; module_param(howmany, int, S_IRUGO); module_param(whom, charp, S_IRUGO);

26 9.ユーザ空間を使う ユーザ空間ドライバの利点 ユーザ空間ドライバを書く場合・・・ Xサーバ Cライブラリをリンクできる
整備されたデバッガでデバックできる ハングしてもシステム全体に影響しない スワップできる(RAMを占有しない) デバイスの同時アクセスを許可できる ライセンスやカーネルインタフェースの変更問題をユーザ空間のオプションによって回避できる ユーザ空間ドライバを書く場合・・・ サーバプロセスをつくり、ハードウェアを制御する唯一の仕事人の役割をカーネルから引き継ぐ Xサーバ

27 9.ユーザ空間を使う 2 ユーザ空間ドライバの欠点 新しいデバイスを扱う場合は、まずはユーザ空間で実装するのも良い 割り込みを使えない
9.ユーザ空間を使う 2 ユーザ空間ドライバの欠点 割り込みを使えない IA32では、vm86システムコールがある メモリへの直接アクセスが/dev/memに対するmmapシステムコールのみしかない I/Oポートへのアクセスは、iopermかiopl呼び出し後にしか行えない 反応に時間がかかる ディスクスワップされている場合は特に! ネットワークインタフェースやブロックデバイスなどはユーザ空間で扱えない 新しいデバイスを扱う場合は、まずはユーザ空間で実装するのも良い


Download ppt "Linux Device Driver 輪講 2. モジュールの作成と実行"

Similar presentations


Ads by Google