Как найти драйвер, ассоциированный с устройством?

Взгляд изнутри

Модератор: Модераторы разделов

Аватара пользователя
жучара
Сообщения: 1174
ОС: Debian 12

Как найти драйвер, ассоциированный с устройством?

Сообщение жучара »

Друзья! Устройство у меня символьное, за основу взял этот код chardev.c из вот этой книги.

Вот мой код, он проще, там функции не определены. Только создание устройства при загрузке модуля и десоздание при выгрузке. Всё.
chardev.c

Код: Выделить всё

/*
 * chardev.c: Creates a read-only char device that says how many times
 * you have read from the dev file
 */

#include <linux/atomic.h>
#include <linux/cdev.h>
#include <linux/delay.h>
#include <linux/device.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/kernel.h> /* for sprintf() */
#include <linux/module.h>
#include <linux/printk.h>
#include <linux/types.h>
#include <linux/uaccess.h> /* for get_user and put_user */
#include <linux/version.h>

#include <asm/errno.h>

#define DEVICE_NAME "chardev" /* Dev name as it appears in /proc/devices   */
#define BUF_LEN 80 /* Max length of the message from the device */

/* Global variables are declared as static, so are global within the file. */

static int major; /* major number assigned to our device driver */

static struct class *cls;

static struct file_operations chardev_fops;

static int __init chardev_init(void)
{
    major = register_chrdev(0, DEVICE_NAME, &chardev_fops);

    if (major < 0) {
        pr_alert("Registering char device failed with %d\n", major);
        return major;
    }

    pr_info("I was assigned major number %d.\n", major);

#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 4, 0)
    cls = class_create(DEVICE_NAME);
#else
    cls = class_create(THIS_MODULE, DEVICE_NAME);
#endif
    if (IS_ERR(cls)) {
        pr_err("Failed to create class for device\n");
        unregister_chrdev(major, DEVICE_NAME);
        return PTR_ERR(cls);
    }
    device_create(cls, NULL, MKDEV(major, 0), NULL, DEVICE_NAME);

    pr_info("Device created on /dev/%s\n", DEVICE_NAME);

    return 0;
}

static void __exit chardev_exit(void)
{
    device_destroy(cls, MKDEV(major, 0));
    class_destroy(cls);

    /* Unregister the device */
    unregister_chrdev(major, DEVICE_NAME);
}

/////////////////////////////////////

module_init(chardev_init);
module_exit(chardev_exit);

MODULE_LICENSE("GPL");
Makefile

Код: Выделить всё

obj-m += chardev.o

PWD := $(CURDIR)

all:
	make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
clean:
	make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
Всё работает нормально (там особенно нечему работать-то), но вот я не пойму, как найти драйвер, с устройством ассоциированный? Ну то есть после загрузке модуля:

Shell

$ sudo insmod chardev.ko
$
Устройство у меня:

Shell

$ ls -l /dev/chardev
crw------- 1 root root 245, 0 июн 9 14:34 /dev/chardev
$
То есть получается, какая-нибудь программа при необходимости может через старший номер 245 устройства найти драйвер устроства (если не ошибаюсь, драйвер это же и есть загруженный модуь chardev.ko?)

А как найтим-то? Вот тут сказано как:
https://www.baeldung.com/linux/find-device-drivers

Но у меня там ничего не получилось, ссылки указывают на папки, где эти ссылки находятся. В общем, я так скопом все дравера посмотрел. Нет здесь номера 245

Shell

$ ls -l /sys/dev/*/*/device/driver
lrwxrwxrwx 1 root root 0 июн 9 14:15 /sys/dev/block/11:0/device/driver -> ../../../../../../../bus/scsi/drivers/sr
lrwxrwxrwx 1 root root 0 июн 9 14:15 /sys/dev/block/8:0/device/driver -> ../../../../../../../bus/scsi/drivers/sd
lrwxrwxrwx 1 root root 0 июн 9 14:15 /sys/dev/char/21:0/device/driver -> ../../../../../../../bus/scsi/drivers/sd
lrwxrwxrwx 1 root root 0 июн 9 14:15 /sys/dev/char/21:1/device/driver -> ../../../../../../../bus/scsi/drivers/sr
lrwxrwxrwx 1 root root 0 июн 9 14:15 /sys/dev/char/226:0/device/driver -> ../../../bus/pci/drivers/vmwgfx
lrwxrwxrwx 1 root root 0 июн 9 14:15 /sys/dev/char/226:128/device/driver -> ../../../bus/pci/drivers/vmwgfx
lrwxrwxrwx 1 root root 0 июн 9 14:15 /sys/dev/char/246:0/device/driver -> ../../../../../../../bus/hid/drivers/hid-generic
lrwxrwxrwx 1 root root 0 июн 9 14:15 /sys/dev/char/248:0/device/driver -> ../../../../../../../bus/scsi/drivers/sd
lrwxrwxrwx 1 root root 0 июн 9 14:15 /sys/dev/char/248:1/device/driver -> ../../../../../../../bus/scsi/drivers/sr
lrwxrwxrwx 1 root root 0 июн 9 14:15 /sys/dev/char/251:0/device/driver -> ../../../bus/platform/drivers/rtc_cmos
lrwxrwxrwx 1 root root 0 июн 9 14:15 /sys/dev/char/29:0/device/driver -> ../../../bus/pci/drivers/vmwgfx
lrwxrwxrwx 1 root root 0 июн 9 14:15 /sys/dev/char/4:64/device/driver -> ../../../bus/platform/drivers/serial8250
lrwxrwxrwx 1 root root 0 июн 9 14:15 /sys/dev/char/4:65/device/driver -> ../../../bus/platform/drivers/serial8250
lrwxrwxrwx 1 root root 0 июн 9 14:15 /sys/dev/char/4:66/device/driver -> ../../../bus/platform/drivers/serial8250
lrwxrwxrwx 1 root root 0 июн 9 14:15 /sys/dev/char/4:67/device/driver -> ../../../bus/platform/drivers/serial8250
$
Грустно как-то. Как же мне на самом деле найти драйвер, ассоциированный с устройством? Спасибо, кто откликнется. Debian 12.
Последний раз редактировалось Bizdelnick 09.06.2026 16:57, всего редактировалось 1 раз.
Причина: тег [code]
Я просто читаю маны.
Спасибо сказали:
math
Сообщения: 312
Статус: Ъ участник
ОС: LMDE

Re: Как найти драйвер, ассоциированный с устройством?

Сообщение math »

Попробуйте cat /proc/devices | grep 245
Добавлено (20:57):
жучара писал(а):
09.06.2026 13:29
Но у меня там ничего не получилось
Естественно, это всё про драйвера реальных железных устройств.
Добавлено (21:00):
Ещё можно попробовать ls -l /sys/class/chardev/chardev/
Спасибо сказали:
Аватара пользователя
жучара
Сообщения: 1174
ОС: Debian 12

Re: Как найти драйвер, ассоциированный с устройством?

Сообщение жучара »

math писал:
09.06.2026 20:55
Попробуйте cat /proc/devices | grep 245
ну допустим

Shell

$ cat /proc/devices | grep 245
245 chardev
$
Выглядит полуубедительно, но не до конца убедительно. Хотелось бы на самом деле убедиться, что что-то там лезет в файл /proc/devices, ищет цифру 245, потом видит ассоциированный с ним модуль chardev и далее по плану. А как убедиться-то? Можно, например, попробовать что-нибудь считать с устройства /dev/chardev, и отрассировать всё это дело. И несомненно в трассировке мы увидим обращение к файлу /proc/devices

Shell

$ sudo strace cat /dev/chardev 2>&1 | grep device
$
а не, не увидели, не обращается оно к файлу /proc/device

В документации про /proc/device тоже молчок. У меня есть файл
fhs-3.0.pdf
так там про /proc сказано очень мало:
6.1.5. /proc : Kernel and process information virtual filesystem

The proc filesystem is the de-facto standard Linux method for handling process and system information,
rather than /dev/kmem and other similar methods. We strongly encourage this for the storage and
retrieval of process information as well as other kernel and memory information.
...Я попыталя поэксперементировать с файлом /proc/device, ну типа вручную поменять соответствие
245 chardev
и посмотреть что будет. Так ведь не даёт менять. Мы похожее обсуждали.

А потому вопрос открыт.
У вас нет необходимых прав для просмотра вложений в этом сообщении.
Я просто читаю маны.
Спасибо сказали:
math
Сообщения: 312
Статус: Ъ участник
ОС: LMDE

Re: Как найти драйвер, ассоциированный с устройством?

Сообщение math »

жучара писал(а):
10.06.2026 17:54
Хотелось бы на самом деле убедиться, что что-то там лезет в файл /proc/devices, ищет цифру 245, потом видит ассоциированный с ним модуль chardev и далее по плану.
Никто так не делает. Приложение просто открывает файл в /dev и работает с ним. Ядро обрабатывает системные вызовы и делегирует их исполнение драйверу через коллбэки.
Спасибо сказали:
Аватара пользователя
/dev/random
Администратор
Сообщения: 5486
ОС: Gentoo

Re: Как найти драйвер, ассоциированный с устройством?

Сообщение /dev/random »

В /proc/devices находится не имя драйвера, а вот это:
жучара писал(а):
09.06.2026 13:29

Код: Выделить всё

#define DEVICE_NAME "chardev" /* Dev name as it appears in /proc/devices   */
Сам chardev.c (и chardev.ko, в который вы его скомпилировали) - это не драйвер в понимании sysfs, а модуль ядра. Драйвер в sysfs - это то, что регистрируется через driver_register или его аналоги, специфичные для подсистемы. Вы никакого драйвера не зарегистрировали, а значит, никакого драйвера нет.

И мне непонятно, что вы вообще пытаетесь выяснить.
Спасибо сказали:
Аватара пользователя
жучара
Сообщения: 1174
ОС: Debian 12

Re: Как найти драйвер, ассоциированный с устройством?

Сообщение жучара »

math писал:
10.06.2026 19:16
жучара писал(а):
10.06.2026 17:54
Хотелось бы на самом деле убедиться, что что-то там лезет в файл /proc/devices, ищет цифру 245, потом видит ассоциированный с ним модуль chardev и далее по плану.
Никто так не делает. Приложение просто открывает файл в /dev и работает с ним. Ядро обрабатывает системные вызовы и делегирует их исполнение драйверу через коллбэки.
я так понимаю, драйвером вы называете модуль chardev.ko? Во всяком случае функции, которые вы называаете калбэками прописаны только в нём. Как ядро или кто там понимает, что нужно при операции, например:

Shell

$cat /dev/chardev
...
$
Обратиться именно к модулю chardev.ko (где прописано тело функции read?)

////////////////////////////////////////////////////
/dev/random писал:
10.06.2026 19:56
В /proc/devices находится не имя драйвера, а вот это:
жучара писал(а):
09.06.2026 13:29

Код: Выделить всё

#define DEVICE_NAME "chardev" /* Dev name as it appears in /proc/devices   */
Сам chardev.c (и chardev.ko, в который вы его скомпилировали) - это не драйвер в понимании sysfs, а модуль ядра. Драйвер в sysfs - это то, что регистрируется через driver_register или его аналоги, специфичные для подсистемы. Вы никакого драйвера не зарегистрировали, а значит, никакого драйвера нет.

И мне непонятно, что вы вообще пытаетесь выяснить.
Хорошо, пусть не драйвер, пусть модуль ядра. А выше я написал, что хочу выяснить. Как ядро или кто там понимает, что нужно при операции, например:

Shell

$cat /dev/chardev
...
$
Обратиться именно к модулю chardev.ko (где прописано тело функции read?) Где-то же должно быть прописано сооветствие /dev/chardev -> chardev.ko Пока вырисовывается вариант через промежуточное звено- номер (245) драйвера и файл /proc/devices, но убедиться в этом нет никакой возможности.
Я просто читаю маны.
Спасибо сказали:
Аватара пользователя
/dev/random
Администратор
Сообщения: 5486
ОС: Gentoo

Re: Как найти драйвер, ассоциированный с устройством?

Сообщение /dev/random »

жучара писал(а):
10.06.2026 20:22
Обратиться именно к модулю chardev.ko (где прописано тело функции read?)
Я не вижу в вашем примере тела функции read. Но если бы оно было, и было прописано здесь:
жучара писал(а):
09.06.2026 13:29

Код: Выделить всё

static struct file_operations chardev_fops;
то ядро загружает модуль (по сути, почти как библиотеку), вызывает инициализирующую функцию, эта функция регистрирует структуру chardev_fops в привязке к новому классу устройств (это запоминается в ядре), и создаёт устройство этого класса. Когда кто-то обращается к устройству, ядро смотрит, какого оно класса, находит в своём внутреннем хранилище вашу структуру, заглядывает в неё, находит в ней указатель на функцию read, и вызывает её. А находится ли эта функция в вашем chardev.ko, ядро не знает и знать не хочет.
Спасибо сказали:
Аватара пользователя
жучара
Сообщения: 1174
ОС: Debian 12

Re: Как найти драйвер, ассоциированный с устройством?

Сообщение жучара »

/dev/random писал:
10.06.2026 20:38
Я не вижу в вашем примере тела функции read.
я дико извиняюсь, зарапортовался уже, вот код из книжки, в нём и прописана функция read
chardev.c
/*
* chardev.c: Creates a read-only char device that says how many times
* you have read from the dev file
*/

#include <linux/atomic.h>
#include <linux/cdev.h>
#include <linux/delay.h>
#include <linux/device.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/kernel.h> /* for sprintf() */
#include <linux/module.h>
#include <linux/printk.h>
#include <linux/types.h>
#include <linux/uaccess.h> /* for get_user and put_user */
#include <linux/version.h>

#include <asm/errno.h>

/* Prototypes - this would normally go in a .h file */
static int device_open(struct inode *, struct file *);
static int device_release(struct inode *, struct file *);
static ssize_t device_read(struct file *, char __user *, size_t, loff_t *);
static ssize_t device_write(struct file *, const char __user *, size_t,
loff_t *);

#define DEVICE_NAME "chardev" /* Dev name as it appears in /proc/devices */
#define BUF_LEN 80 /* Max length of the message from the device */

/* Global variables are declared as static, so are global within the file. */

static int major; /* major number assigned to our device driver */

enum {
CDEV_NOT_USED,
CDEV_EXCLUSIVE_OPEN,
};

/* Is device open? Used to prevent multiple access to device */
static atomic_t already_open = ATOMIC_INIT(CDEV_NOT_USED);

static char msg[BUF_LEN + 1]; /* The msg the device will give when asked */

static struct class *cls;

static struct file_operations chardev_fops = {
.read = device_read,
.write = device_write,
.open = device_open,
.release = device_release,
};

static int __init chardev_init(void)
{
major = register_chrdev(0, DEVICE_NAME, &chardev_fops);

if (major < 0) {
pr_alert("Registering char device failed with %d\n", major);
return major;
}

pr_info("I was assigned major number %d.\n", major);

#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 4, 0)
cls = class_create(DEVICE_NAME);
#else
cls = class_create(THIS_MODULE, DEVICE_NAME);
#endif
if (IS_ERR(cls)) {
pr_err("Failed to create class for device\n");
unregister_chrdev(major, DEVICE_NAME);
return PTR_ERR(cls);
}
device_create(cls, NULL, MKDEV(major, 0), NULL, DEVICE_NAME);

pr_info("Device created on /dev/%s\n", DEVICE_NAME);

return 0;
}

static void __exit chardev_exit(void)
{
device_destroy(cls, MKDEV(major, 0));
class_destroy(cls);

/* Unregister the device */
unregister_chrdev(major, DEVICE_NAME);
}

/* Methods */

/* Called when a process tries to open the device file, like
* "sudo cat /dev/chardev"
*/
static int device_open(struct inode *inode, struct file *file)
{
static int counter = 0;

if (atomic_cmpxchg(&already_open, CDEV_NOT_USED, CDEV_EXCLUSIVE_OPEN))
return -EBUSY;

sprintf(msg, "I already told you %d times Hello world!\n", counter++);

return 0;
}

/* Called when a process closes the device file. */
static int device_release(struct inode *inode, struct file *file)
{
/* We're now ready for our next caller */
atomic_set(&already_open, CDEV_NOT_USED);

return 0;
}

/* Called when a process, which already opened the dev file, attempts to
* read from it.
*/
static ssize_t device_read(struct file *filp, /* see include/linux/fs.h */
char __user *buffer, /* buffer to fill with data */
size_t length, /* length of the buffer */
loff_t *offset)
{
/* Number of bytes actually written to the buffer */
int bytes_read = 0;
const char *msg_ptr = msg;

if (!*(msg_ptr + *offset)) { /* we are at the end of message */
*offset = 0; /* reset the offset */
return 0; /* signify end of file */
}

msg_ptr += *offset;

/* Actually put the data into the buffer */
while (length && *msg_ptr) {
/* The buffer is in the user data segment, not the kernel
* segment so "*" assignment won't work. We have to use
* put_user which copies data from the kernel data segment to
* the user data segment.
*/
put_user(*(msg_ptr++), buffer++);
length--;
bytes_read++;
}

*offset += bytes_read;

/* Most read functions return the number of bytes put into the buffer. */
return bytes_read;
}

/* Called when a process writes to dev file: echo "hi" | sudo tee /dev/chardev */
static ssize_t device_write(struct file *filp, const char __user *buff,
size_t len, loff_t *off)
{
pr_alert("Sorry, this operation is not supported.\n");
return -EINVAL;
}

module_init(chardev_init);
module_exit(chardev_exit);

MODULE_LICENSE("GPL");
Makefile
obj-m += chardev.o

PWD := $(CURDIR)

all:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
clean:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
/dev/random писал:
10.06.2026 20:38
ядро загружает модуль (по сути, почти как библиотеку), вызывает инициализирующую функцию, эта функция регистрирует структуру chardev_fops в привязке к новому классу устройств (это запоминается в ядре), и создаёт устройство этого класса. Когда кто-то обращается к устройству, ядро смотрит, какого оно класса, находит в своём внутреннем хранилище вашу структуру, заглядывает в неё, находит в ней указатель на функцию read, и вызывает её. А находится ли эта функция в вашем chardev.ko, ядро не знает и знать не хочет.
ладно, ядро ищет функции и не ищет непосредственно ни модуль, ни драйвер... Короче, не ищет. А просто человек может найти модуль, ассоциированный с устройством? Ну вот как здесь, примерно.
https://www.baeldung.com/linux/find-device-drivers
Я просто читаю маны.
Спасибо сказали: