В Linux, как вы используете device_create в существующем классе?
Примечание.. Я перечисляю эту проблему, как и сегодня, я не против изменения реализации (например, перемещение создания класса в общую область), если это делает вещи проще... Я просто не знаю, как это сделать. : Конечная записка
У меня есть два модуля ядра Linux, и я пытаюсь обновить их /sys. Поиск в google и других источниках, я видел много кода в строках:
static dev_t MyDev;
static struct class *c1;
static int __init start_func(void)
{
...
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);
....
И я проверил для своего первого модуля этот код работает и что он правильно создает:
/sys/class/chardrv/<MODULE_NAME>
запись. Я хотел бы знать, как создать устройство в существующем классе. Другими словами, один из моих модулей создал этот новый класс chardrv, теперь я хочу, чтобы мой другой модуль мог также зарегистрировать свои устройства в одном классе.
Я не могу снова вызвать class_create() (во втором модуле), потому что этот класс "chardrv" уже существует...
Итак, я могу запустить проверку, чтобы увидеть, существует ли /sys/class/chardrv, и это может помочь мне решить, нужно ли мне вызвать class_create() или нет, это не проблема. Здесь можно внести некоторые псевдокоды:
if ( path "/sys/class/chardrv" does not exist)
new_class = class_create("chardrv")
else
new_class = some how get class "chardrv" handle, or properties, or whatever
device_create(new_class, ...)
Итак, как в этом примере, если мой класс уже существует, и я просто хочу добавить в него свое новое устройство из второго модуля, я предполагаю, что мне нужно создать структуру класса и как-то заполнить его с правильными атрибутами класса chardrv, тогда вызовите device_create, как и раньше, но я не уверен, как это сделать.
Ответы
Ответ 1
Чтобы использовать функцию device_create
с тем же классом, просто передайте ей указатель на тот же класс.
Поскольку вы хотите вызвать device_create
в другом модуле, чем тот, в котором вы создаете класс, вам нужно будет экспортировать символ для указателя на класс. Вы можете использовать макрос EXPORT_SYMBOL
, чтобы сделать это.
Например:
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");
....
}
Примечание. Вам нужно будет вставить module1 до module2, поскольку указатель класса определен и экспортирован в module1.
Это должно создать каталоги, которые вы ожидаете:
-
/sys/class/chardrv/mod1_dev
-
/sys/class/chardrv/mod2_dev
Кстати, если вы получаете ошибку Invalid parameters
при попытке загрузить второй модуль, вам может потребоваться добавить строку KBUILD_EXTRA_SYMBOLS
в ваш Makefile.
Ответ 2
Чтобы следовать вашему примеру, вы просто вызываете device_create()
снова, передавая тот же класс, например:
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");
Вам определенно не нужно проверять путь, чтобы определить, был ли класс создан. Вы создаете его в своем коде, поэтому просто проверяйте c1 == NULL
или используйте флаг, если вам нужно.
Ответ 3
Ядро Linux не позволит этого сделать. Это ОШИБКА, которую вы получите.
**[ 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)