2008-09-11
キャラクタ型デバイス 3分コーディング
はじめに
特に,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 <linux/module.h>
#include <linux/miscdevice.h>
#include <linux/fs.h>
#include <linux/poll.h>
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分てことない...
おわりに
キャラクタ型デバイス作成において,miscデバイスを利用することでより簡易に作成できる.
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によりデバイスファイルを管理していることがわかる.
トラックバック - http://d.hatena.ne.jp/TRANSii/20080911/p1
リンク元
- 1 http://d.hatena.ne.jp/keyword/カーネル
- 1 http://d.hatena.ne.jp/keyword/GPL
- 1 http://www.google.co.jp/search?hl=ja&client=firefox-a&rls=org.mozilla:ja:official&q=シリアル The+other+end+is&btnG=検索&lr=lang_ja
- 1 http://www.google.co.jp/search?hl=ja&lr=lang_ja&rls=GGGL,GGGL:2006-46,GGGL:ja&q=vmware+シリアルポート&start=10&sa=N
- 1 http://www.google.co.jp/search?q=シリアル 設定+centos&hl=ja&lr=&sa=2