キャラクタ型デバイス 3分コーディング
キャラクタ型ドライバのテンプレート
環境: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);
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分てことない...
Appendix
udevについて
- strace -f /sbin/udevd
- insmod simple.ko
- 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によりデバイスファイルを管理していることがわかる.