Драйверы шин (Bus Core Drivers)
Для каждой шины, поддерживаемой ядром Linux, существует соответствующий драйвер шины (bus core driver). Шина это канал связи между процессором и одним или несколькими устройствами. С точки зрения модели устройств Linux, все устройства подключены через шину, даже если она виртуальная, внутренняя или «платформенная» (platform bus).
Описание bus_type
Каждый драйвер шины выделяет и регистрирует структуру bus_type:
struct bus_type {
const char *name;
const char *dev_name;
struct device *dev_root;
struct device_attribute *dev_attrs;
const struct attribute_group **bus_groups;
const struct attribute_group **dev_groups;
const struct attribute_group **drv_groups;
int (*match)(struct device *dev, struct device_driver *drv);
int (*uevent)(struct device *dev, struct kobj_uevent_env *env);
int (*probe)(struct device *dev);
int (*remove)(struct device *dev);
void (*shutdown)(struct device *dev);
int (*online)(struct device *dev);
int (*offline)(struct device *dev);
int (*suspend)(struct device *dev, pm_message_t state);
int (*resume)(struct device *dev);
const struct dev_pm_ops *pm;
struct iommu_ops *iommu_ops;
struct subsys_private *p;
struct lock_class_key lock_key;
};
Регистрация новой шины осуществляется с помощью функции bus_register(). Например, для платформенной
шины:
struct bus_type platform_bus_type = {
.name = "platform",
.dev_groups = platform_dev_groups,
.match = platform_match,
.uevent = platform_uevent,
.pm = &platform_dev_pm_ops,
};
EXPORT_SYMBOL_GPL(platform_bus_type);
int __init platform_bus_init(void)
{
int error;
early_platform_cleanup();
error = device_register(&platform_bus);
if (error)
return error;
error = bus_register(&platform_bus_type);
if (error)
device_unregister(&platform_bus);
return error;
}
После вызова bus_register(), ядро создаёт директорию /sys/bus/platform/, содержащую
поддиректории devices/ и drivers/.
subsys_private и списки устройств/драйверов
Один из членов struct bus_type это указатель на структуру subsys_private, определённую
в drivers/base/base.h:
struct subsys_private {
struct kset subsys;
struct kset *devices_kset;
struct list_head interfaces;
struct mutex mutex;
struct kset *drivers_kset;
struct klist klist_devices;
struct klist klist_drivers;
struct blocking_notifier_head bus_notifier;
unsigned int drivers_autoprobe:1;
struct bus_type *bus;
struct kset glue_dirs;
struct class *class;
};
Списки klist_devices и klist_drivers содержат, соответственно, все устройства и драйверы,
зарегистрированные на данной шине. Они обновляются функциями:
device_register()при добавлении устройства;driver_register()при инициализации драйвера.
Алгоритм привязки устройства к драйверу
Когда новое устройство подключается, драйвер контроллера шины вызывает
device_register().Ядро перебирает список драйверов на шине и вызывает
match(), чтобы найти подходящий драйвер.При совпадении вызывается функция
probe()драйвера происходит привязка (binding).
И наоборот:
Если сначала загружается драйвер, то
driver_register()вызывает сопоставление с уже существующими устройствами.
Итог: привязка возможна как при появлении устройства, так и при загрузке драйвера.
Назначение драйвера шины
Драйвер шины (bus core driver):
Регистрирует шину в системе.
Позволяет регистрировать драйверы контроллеров шин (например, PCI, USB контроллеры).
Позволяет регистрировать драйверы устройств.
Выполняет сопоставление устройств с драйверами с помощью функции
match().
—
Примечание: Вы можете исследовать структуру и реализацию этих механизмов в Linux-ядре через [elixir.bootlin.com](https://elixir.bootlin.com/linux/latest/source) отличный ресурс для просмотра исходников с удобной навигацией и кросс-ссылками.