キャラクタ型デバイス 3分コーディング

はじめに

Linuxにおけるキャラクタ型デバイスを簡単に作成する.
特に,dirty hackingや 簡易テストドライバ作成の際して,手軽に作成したい.
#というか,テンプレートのメモ置き

キャラクタ型ドライバのテンプレート

環境:CentOS 5

作成するキャラクタ型ドライバをmiscellaneous deviceとすることで,極めて簡単に作成できる.

  • struct miscdeviceを定義
  • miscデバイスのstruct file_operationsを定義
  • misc_register()をコール

ただそれだけ.
また,udevdが起動しており,かつsysfsが/sysにmountされていれば,udevdがinmod時にキャラクタデバイスファイルも作成してくれる.
rmmod時にはキャラクタデバイスファイルを削除してくれる.
したがって,ユーザがmajor/minorおよびデバイスファイルの作成・管理をする必要もない.

simple.c

#include 
#include 
#include 
#include 

static int simple_open(struct inode *inode, struct file *filp)
{
	printk("%s\n", __func__);
	/* */
	return 0;
}

static ssize_t simple_read(struct file *filp, char __user *buf,
			   size_t count, loff_t *ppos)
{
	printk("%s\n", __func__);
	return 0;
}

static ssize_t simple_write(struct file *filp, const char __user *buf,
			    size_t count, loff_t *ppos)

{
	printk("%s\n", __func__);
	return count;
}

static int simple_release(struct inode *inode, struct file *filp)
{
	printk("%s\n", __func__);
	return 0;
}

static unsigned int simple_poll(struct file *filp, poll_table *wait)
{
	printk("%s\n", __func__);
	return 0;
}


static int simple_ioctl(struct inode *inode, struct file *filp,
			unsigned int cmd, unsigned long arg)
{
	printk("%s\n", __func__);
	return  -ENOTTY;
}

static struct file_operations simple_fops = {
	.owner		= THIS_MODULE,
	.read		= simple_read,
	.write		= simple_write,
	.poll		= simple_poll,
	.ioctl		= simple_ioctl,
	.open		= simple_open,
	.release	= simple_release,
};

static struct miscdevice simple_dev = {
	.minor = MISC_DYNAMIC_MINOR,
	.name = "simple",
	.fops = &simple_fops,
};


static int __init simple_init(void)
{
	int ret;

	ret = misc_register(&simple_dev);
	if (ret) {
		printk("fail to misc_register (MISC_DYNAMIC_MINOR)\n");
		return ret;
	}
	
	printk("Succefully loaded.\n");
	return 0;
}

static void __exit simple_cleanup(void)
{
	misc_deregister(&simple_dev);
 	printk("Unloaded.\n"); 
}

MODULE_LICENSE("GPL");
module_init(simple_init);
module_exit(simple_cleanup);

Makefile

ifneq ($(KERNELRELEASE),)

obj-m		:= simple.o

else

KDIR		:= /lib/modules/$(shell uname -r)/build

all:
	$(MAKE) -C $(KDIR) SUBDIRS=$(PWD) V=1 modules
clean:
	$(MAKE) -C $(KDIR) SUBDIRS=$(PWD) clean 
endif

これをテンプレートに実際の中身を作成していけばよい.
# ここまでは,3分だが,file_operationsの中身を始め,ドライバのデザイン・インプリは3分てことない...

おわりに

キャラクタ型デバイス作成において,miscデバイスを利用することでより簡易に作成できる.

Appendix

udevについて
  1. strace -f /sbin/udevd
  2. insmod simple.ko
  3. rmmod simple.ko

より,/sbin/udevdのシステムコールトレースによる挙動が把握できる.

...
select(8, [3 4 5 7], NULL, NULL, NULL
...
[pid  3127] mknod("/dev/simple", S_IFCHR|0600, makedev(10, 62)) = 0
...
[pid  3146] unlink("/dev/simple")       = 0
...

上記トレースより,udevdは,カーネルからのイベント(via netlink)をselect待ちし,insmod/rmmod後にイベント受信して,それぞれmknod/unlinkによりデバイスファイルを管理していることがわかる.