簡単なのから

順に作ってみよう。まず open/close 対応なソレから。簡単なキャラクタデバイスを作るを参考にしつつ。

とりあえず

デバイスファイル作らんと。メジャー番号は 128 とか空いてそげ。こんなカンジ?

# mknod /dev/fifo100128 c 128 100
# mknod /dev/fifo101128 c 128 101
# ls /dev/fifo10* -l
crw-r--r-- 1 root root 128, 100 Aug 13 22:41 /dev/fifo100128
crw-r--r-- 1 root root 128, 101 Aug 13 22:41 /dev/fifo101128
# 

一応なんとかなっている模様。次は実装。ええと open/close の前に register_chrdev と unregister_chrdev の使い方というあたりを参考にしつつ以下。

#include <linux/module.h>   // required by all modules
#include <linux/kernel.h>   // required by printk()
#include <linux/init.h>
#include <linux/fs.h>

MODULE_LICENSE("GPL");

#define DRIVERNAME "yamanetoshi"
int fifo_major = 128;

struct file_operations fifo_fops = {
	.owner = NULL,
	.read = NULL,
	.write = NULL,
	.ioctl = NULL,
	.open = NULL,
	.release = NULL,
};

// Start/Init function
static int yamanetoshi_init(void) {
	int ret;

	printk("initialize the fifo device\n");
	ret = register_chrdev(fifo_major, DRIVERNAME, &fifo_fops);

	if(ret < 0)
		return ret;

	if(fifo_major == 0)
		fifo_major = ret;

    return 0;
}

// End/Cleanup function
static void yamanetoshi_exit(void) {
	printk("cleanup the fifo device\n");
	unregister_chrdev(fifo_major, DRIVERNAME);
}

module_init(yamanetoshi_init);
module_exit(yamanetoshi_exit);

動作確認

insmod してみたら以下

# insmod yamanetoshi.ko 
insmod: error inserting 'yamanetoshi.ko': -1 Device or resource busy
#

む。128 は SCSI 用にアサイン済みなのか (Documentation/devices.txt)。ええと、130 でヤッてみます。とりあえずデバイス消して再度作成

# rm -rf /dev/fifo10*
# mknod /dev/fifo100130 c 130 100
# mknod /dev/fifo101130 c 130 101
#

でソース直して make して insmod と rmmod してみたら一応以下が出力

# tail -f /var/log/messages
Aug 13 22:41:09 debian -- MARK --
Aug 13 22:52:46 debian kernel: initialize the fifo device
Aug 13 23:02:03 debian kernel: initialize the fifo device
Aug 13 23:02:45 debian kernel: cleanup the fifo device

printk はいっちゃん最後の方が良いな。次は open/close か。

open/close

とりあえず i/f だけ。以下なカンジ

#include <linux/module.h>   // required by all modules
#include <linux/kernel.h>   // required by printk()
#include <linux/init.h>
#include <linux/fs.h>

MODULE_LICENSE("GPL");

#define DRIVERNAME "yamanetoshi"
int fifo_major = 130;

static int yamanetoshi_open(struct inode *inode, struct file *file)
{
	printk("yamanetoshi_open\n");
	printk(" file->f_version     : %lu\n", file->f_version);
	printk(" MINOR(inode->i_rdev): %d\n", MINOR(inode->i_rdev));
	return 0;
}

static int yamanetoshi_release(struct inode *inode, struct file *file)
{
	printk("yamanetoshi_close\n");
	printk(" file->f_version     : %lu\n", file->f_version);
	return 0;
}

struct file_operations fifo_fops = {
	.owner = NULL,
	.read = NULL,
	.write = NULL,
	.ioctl = NULL,
	.open = yamanetoshi_open,
	.release = yamanetoshi_release,
};

// Start/Init function
static int yamanetoshi_init(void) {
	int ret;

	printk("initialize the fifo device\n");
	ret = register_chrdev(fifo_major, DRIVERNAME, &fifo_fops);

	if(ret < 0)
		return ret;

	if(fifo_major == 0)
		fifo_major = ret;

    return 0;
}

// End/Cleanup function
static void yamanetoshi_exit(void) {
	printk("cleanup the fifo device\n");
	unregister_chrdev(fifo_major, DRIVERNAME);
}

module_init(yamanetoshi_init);
module_exit(yamanetoshi_exit);

コンパイルしてみる。

# make
make -C /lib/modules/2.6.20/build M=/home/rms/kernel/kernel_exercise/5.driver_exercize modules
make[1]: Entering directory `/home/rms/kernel/linux-2.6.20'
  CC [M]  /home/rms/kernel/kernel_exercise/5.driver_exercize/yamanetoshi.o
  Building modules, stage 2.
  MODPOST 1 modules
  LD [M]  /home/rms/kernel/kernel_exercise/5.driver_exercize/yamanetoshi.ko
make[1]: Leaving directory `/home/rms/kernel/linux-2.6.20'
#

パス。insmod したら??

# insmod yamanetoshi.ko
#

syslog に以下のメセジ出力を確認

Aug 13 23:24:16 debian kernel: initialize the fifo device

で、試験用の以下のプログラムを用意

#include <stdio.h>
#include <stdlib.h>

int main(void)
{
	FILE *fptr = NULL;
	if(NULL == (fptr = fopen("/dev/fifo100130", "r"))) {
		fprintf(stderr, "open error /dev/fifo100130");
		exit(1);
	}

	fclose(fptr);
	fptr = NULL;

	return 0;
}

コンパイルして実行。

$ gcc -o test_yamanetoshi -Wall test_yamanetoshi.c
$ ./test_yamanetoshi
$

syslog のメセジが以下

Aug 13 23:26:05 debian kernel: yamanetoshi_open
Aug 13 23:26:05 debian kernel:  file->f_version     : 0
Aug 13 23:26:05 debian kernel:  MINOR(inode->i_rdev): 100
Aug 13 23:26:05 debian kernel: yamanetoshi_close
Aug 13 23:26:05 debian kernel:  file->f_version     : 0

f_version 属性のナニが不明ですが、一応何とかなってる模様。今後もコツコツ進めます。