linux MISC駆動モデル解析
linux MISC
ledドライバのコードを読むとldd 3に記載されている各種文字デバイス登録関数ではなくmisc_が見つかりましたregister関数、これはledデバイスがヘテロデバイスとしてカーネルに現れていることを示しています.カーネルではmiscヘテロデバイス駆動インタフェースはいくつかの文字デバイスの簡単なパッケージであり、彼らは1つのプライマリデバイス番号を共有し、異なるセカンダリデバイス番号を共有し、open呼び出しを共有し、その彼の操作関数は開いた後にlinuxドライバの方法で再ロードされてマウントされます.
1.主なデータ構造
misc_list ,misc misc_register , misc_deregister 。 miscdevice。 :
struct miscdevice {
int minor;
const char *name;
const struct file_operations *fops;
struct list_head list;
struct device *parent;
struct device *this_device;
const char *nodename;
mode_t mode;
};
misc , misc , name minor fops 。 led miscdevice :
static struct miscdevice misc = {
.minor = MISC_DYNAMIC_MINOR,
.name = DEVICE_NAME,
.fops = &dev_fops,
};
fops open , misc_ops open 。 minor MISC_DYNAMIC_MINOR, , misc_register 。
2. misc_init関数
misc , 。 misc 。
static int __init misc_init(void)
{
int err;
#ifdef CONFIG_PROC_FS
proc_create("misc", 0, NULL, &misc_proc_fops);
#endif
misc_class = class_create(THIS_MODULE, "misc");
//udev
err = PTR_ERR(misc_class);
if (IS_ERR(misc_class))
goto fail_remove;
err = -EIO;
if (register_chrdev(MISC_MAJOR,"misc",&misc_fops)) //
goto fail_printk;
misc_class->devnode = misc_devnode;
return 0;
fail_printk:
printk("unable to get major %d for misc devices
", MISC_MAJOR);
class_destroy(misc_class);
fail_remove:
remove_proc_entry("misc", NULL);
return err;
}
, , , 2.4 register_chrdev。 MISC_MAJOR, 0-255 256 。 misc 。
3. misc_register()関数
misc_register() misc.c , misc_class , miscdevice misc_list , linux , miscdevice 。
int misc_register(struct miscdevice * misc)
{
struct miscdevice *c;
dev_t dev;
int err = 0;
INIT_LIST_HEAD(&misc->list); //
mutex_lock(&misc_mtx);
list_for_each_entry(c, &misc_list, list) {
if (c->minor == misc->minor) {
mutex_unlock(&misc_mtx);
return -EBUSY;
}
} // ,
if (misc->minor == MISC_DYNAMIC_MINOR) { //
int i = DYNAMIC_MINORS;
while (--i >= 0)
if ( (misc_minors[i>>3] & (1 << (i&7))) == 0)
break;
if (i<0) {
mutex_unlock(&misc_mtx);
return -EBUSY;
}
misc->minor = i;
}
if (misc->minor < DYNAMIC_MINORS)
misc_minors[misc->minor >> 3] |= 1 << (misc->minor & 7);
dev = MKDEV(MISC_MAJOR, misc->minor);
misc->this_device = device_create(misc_class, misc->parent, dev,
misc, "%s", misc->name);
//udev ,linux
if (IS_ERR(misc->this_device)) {
err = PTR_ERR(misc->this_device);
goto out;
}
/*
* Add it to the front, so that later devices can "override"
* earlier defaults
*/
list_add(&misc->list, &misc_list); // misc_list
out:
mutex_unlock(&misc_mtx);
return err;
}
, misc_list , , 。 , MKDEV , misc MISC_MAJOR, device_create, 。 misc_list 。
device_create,class_create : class_create misc.c , 。 , ldd3 , class_create __class_regsiter() 。 device_create , device_register 。 linux , linux 2.6 ,devfs ,udev devfs 。 devfs,udev 。
struct class *myclass = class_create(THIS_MODULE, “my_device_driver”);
class_device_create(myclass, NULL, MKDEV(major_num, 0), NULL, “my_device”);
, ,udev daemon /dev my_device 。 。 。
4.まとめ
, , , , , miscdevice , misc_register 。 255 , 。 ,mini2440 , mini2440_buttons,mini2440_adc,mini2440_pwm 。