In Linux, how do you use device_create within an existing class?

情到浓时终转凉″ 提交于 2019-12-04 23:51:49
Vilhelm Gray

To use the device_create function with the same class, just pass it a pointer to the same class.

Since you want to call device_create in a different module than the one in which you create the class, you'll need to export the symbol for the pointer to the class. You can use the EXPORT_SYMBOL macro to do this.


For example:

module1.c:

extern struct class *c1;    /* declare as extern */
EXPORT_SYMBOL(c1);          /* use EXPORT_SYMBOL to export c1 */

static dev_t mod1_dev;
static int __init start_func(void)
{
        ...
        /* define class here */
        c1 = class_create(THIS_MODULE, "chardrv");

        /* create first device */
        device_create(c1, NULL, mod1_dev, NULL, "mod1_dev");
        ....
}

module2.c

extern struct class *c1;    /* declare as extern */

static dev_t mod2_dev;
static int __init start_func(void)
{
        ...
        /* c1 is defined in module 1 */

        /* create second device */
        device_create(c1, NULL, mod2_dev, NULL, "mod2_dev");
        ....
}

Note: You'll need to insert module1 before module2 since the class pointer is defined and exported in module1.

That should create the directories you are expecting:

  • /sys/class/chardrv/mod1_dev
  • /sys/class/chardrv/mod2_dev

By the way, if you are getting an Invalid parameters error when you try to load the second module, you might have to add a KBUILD_EXTRA_SYMBOLS line to your Makefile.

To follow your example code, you would simply call device_create() again, passing the same class, eg:

MyDev = MKDEV(nMajor, MINOR_VERSION);
register_chrdev_region(MyDev, 1, MODULE_NAME);
c1 = class_create(THIS_MODULE, "chardrv");
device_create(c1, NULL, MyDev, NULL, MODULE_NAME);
...
device_create(c1, NULL, MyDev2, NULL, "mydev2");

You should definitely not need to check the path in order to determine if the class has been created. You are creating it in your code, so simply test for c1 == NULL or use a flag if you must.

Just create the class in the module init function of your first module, export the - global - class symbol with EXPORT_SYMBOL and use it from the other module.

Since the owner of the class is your first module, every time you add a device to that class the first module's reference counter will be increased: you cannot unload it while anyone is using it.

Linux kernel won't allow to do that. This is the ERROR you will get.

**[  865.687824] kobject_add_internal failed for net with -EEXIST, don't try to register things with the same name in the same directory.  
[  865.687835] Pid: 6382, comm: insmod Tainted: P        W  O 3.2.16.1JeshuLinux #1  
[  865.687840] Call Trace:  
[  865.687849]  [<c1584382>] ? printk+0x2d/0x2f  
[  865.687859]  [<c12a5438>] kobject_add_internal+0x138/0x1d0  
[  865.687869]  [<c12a5a11>] kset_register+0x21/0x50  
[  865.687879]  [<c137b63d>] __class_register+0xcd/0x1b0  
[  865.687888]  [<f8d0a0aa>] hello_init+0x4a/0x80 [sysfs_Dev]  
[  865.687897]  [<c1003035>] do_one_initcall+0x35/0x170    
[  865.687909]  [<f8d0a060>] ? enable_show+0x40/0x40 [sysfs_Dev]    
[  865.687919]  [<c10928d0>] sys_init_module+0x2c0/0x1b50    
[  865.687941]  [<c159485f>] sysenter_do_call+0x12/0x28    
[  865.687947] Registering Class Failed**  

If you want to understand sysfs read: [mochel.pdf](www.kernel.org/pub/linux/kernel/people/mochel/doc/papers/ols-2005/mochel.pdf)
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!