|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
カーネル関連 Linux-2.6カーネルやデバイスドライバ関連のメモ linux-2.6のコンパイルmake xconfig には Qtライブラリが必要 # apt-get install libqt3-dev linux-2.6でモジュールを操作するにはmodule-init-toolsが必要。 従来の modutils の置き換え # apt-get install module-init-tools configのメモLoadable module support ---> [*] Module unloading を有効にしないと rmmod 出来なくなる [ ] Preemptible Kernel プリエンプション linux-2.6デバイスドライバのコンパイル、ロード、アンロードlinux-2.6のデバイスドライバをコンパイルするには、カーネルをビルドしたソースツリー一式が必要となる。(2.4の時と同じ) hello.c ソースコード /*
* hello.c demo driver program for linux-2.6
* Ver0.1 2005-04-13 Y.Ebihara
*/
#include <linux/init.h>
#include <linux/module.h>
MODULE_LICENSE("GPL");
static int hello_init(void){
printk(KERN_ALERT "hello, world\n");
return 0;
}
static void hello_exit(void){
printk(KERN_ALERT "good bye\n");
}
module_init(hello_init);
module_exit(hello_exit);
Makefile(1行のみ!!) obj-m := hello.o コンパイルの実行 $ make -C ~/kernel/linux-2.6.11.7 M=`pwd` modules make: Entering directory `/home/ebihara/kernel/linux-2.6.11.7' CC [M] /home/ebihara/project/preemption/hello/hello.o Building modules, stage 2. MODPOST CC /home/ebihara/project/preemption/hello/hello.mod.o LD [M] /home/ebihara/project/preemption/hello/hello.ko make: Leaving directory `/home/ebihara/kernel/linux-2.6.11.7' -C でカーネルをビルドしたディレクトリを指定する ロード # insmod hello.ko アンロード # rmmod hello キャラクタデバイスの登録静的割り当てlinux-2.4の頃と同じく register_chrdev(), unregister_chrdev() でもok。 デバイス番号(メジャー、マイナー)の自動割り当てint alloc_chrdev_region(dev_t *dev, unsigned baseminor, unsigned count,
const char *name)
dev_t *dev 保存先 割り当て結果dev_t変数ポインタ
unsigned int baseminor マイナー番号の開始番号
unsigned int count 割り当てるマイナー番号の数
const char *name デバイス名
void cdev_init(struct cdev *cdev, struct file_operations *fops) struct cdev *cdev 保存先 キャラクタデバイス構造体ポインタ struct file_operations *fops ファイルオペレーションズ構造体 int cdev_add(struct cdev *p, dev_t dev, unsigned count) struct cdev *p 登録するキャラクタデバイス構造体 dev_t dev デバイス unsigned count 数 を使う。以下sample dev_t devno;
minor = 0;
devno = 0;
// キャラクターデバイス番号の動的割り当て
result = alloc_chrdev_region(&devno, minor, WAKEUPDRV_MINOR_NUMS, DEVNAME);
if(result<0){
printk(KERN_WARNING DEVNAME ":can't get major %d\n",major);
return result;
}
major = MAJOR(devno);
printk(KERN_NOTICE DEVNAME ":major=%d\n",major);
// キャラクターデバイスの登録(マイナー番号の数だけ)
for(i=0; i<COUNTDRV_MINOR_NUMS; i++){
result = countdrv_cdevs_init(&countdrv_dev[i],i);
if(result){
return result;
}
}
int countdrv_cdevs_init(struct countdrv_dev *dev, int mi)
{
int err;
int devno;
/*
* MKDEV(major, minor)
*/
devno = MKDEV(major, mi);
cdev_init(&dev->cdev, &countdrv_fops);
dev->cdev.owner = THIS_MODULE;
// キャラクタデバイスの登録(*cdev, 最初のデバイス番号, 登録するデバイス数)
err = cdev_add(&dev->cdev, devno, 1);
if(err){
printk(KERN_NOTICE "error %d adding chrdev %d",err,mi);
return err;
}
dev->counter = 0; // カウンター変数の初期化
return 0;
}
I/Oアドレス予約struct resource * request_region(start,n,name) 失敗したらNULLが返る プロセスの休眠、起床interruptible_sleep_on(&q)やwake_up_interruptible(&q)はlinux-2.4と同じで変更無し。 wait_queue_head_t q; 待ち列q init_waitqueue_head(&q); qの初期化 interruptible_sleep_on(&q); qにつないで寝る wake_up_interruptible(&q); qにつながっている全プロセスを起こす linux-2.4と変更無いがinterruptible_sleep_on()を使うのはもはや推奨されない。 wait_event_interruptible(q, 式); // qには&を付けないこと // 式が「成立するまで」待つ を用いる。以下に例 err=wait_event_interruptible(parasw_read_wait, (parasw_inp != parasw_file->readout) );
if(err<0){
return err;
}
/* シグナル(ctrl+c等)によって中断したならfs層に処理を依頼 */
if(signal_pending(current)){
return -ERESTARTSYS;
}
割り込みTopHalf上半分はlinux-2.4とあまり変わらない。 void parasw_interrupt(int irq_no, void *dev_id, struct pt_regs *regs){
}
だったものが irqreturn_t parasw_interrupt(int irq_no, void *dev_id, struct pt_regs *regs){
:処理
return IRQ_HANDLED;
}
に変更になった。 BottomHalf下半分はlinux-2.4と同じくTaskletsを使う方法とWorkqueueを使う方法がある。Taskletsは割り込み期間で動く。Workletsはカーネル内部を走行している専用のスレッドで実行されるためsleepに入ることが許される。 #include <linux/workqueue.h>
// ワークキュー関数
static void parasw_bh(void *unused){
wake_up_interruptible(¶sw_read_wait);
}
// ワークキューの定義
DECLARE_WORK(parasw_bh_wq, parasw_bh, NULL);
// ワークキューのスケジュール schedule_work(¶sw_bh_wq); モジュールパラメータモジュールパラメータは module_param()マクロで定義する。 module_param(io,int,0644); module_param(irq,int,0644); module_param(parasw_buf,ulong,444); リンク
関連 |