魔術師見習いのノート

プロフィール

魔術師見習い
Author魔術師見習い-_-.
Twitter魔術師見習い

コンピュータ関係のメモを主に書きます.

MENU

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論理値
invboolboolの逆の値
charp文字列へのポインタ値.
short整数値符号付き
int
long
ushort符号なし
uint
ulong
perm
パーミッション値.誰がsysfsに現れるモジュールパラメータにアクセスできるかを制御する.この引数には<linux/stat.h>にある定義を使用する.例えば,"S_IRUGO|S_IWUSR"はルートがパラメータを変更することを許可する.
module_paramを利用した例を以下に示す.
#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を返す.

一覧