Состояние каждой карты (адреса ввода / вывода, IRQ и т. Д.) Сохраняется в специфической для драйвера структуре, которая передается (прямо или косвенно) каждой точке входа драйвера, которая может таким образом дифференцировать карты , Таким образом, один и тот же код может управлять разными картами (это означает, что да, ядро хранит только один экземпляр модуля драйвера независимо от количества устройств, которыми оно управляет).
Например, посмотрите на drivers/video/backlight/platform_lcd.c
, который является очень простым драйвером питания ЖК-дисплея. Он содержит структуру с именем platform_lcd
, которая является приватной для этого файла и хранит состояние ЖК-дисплея (включен ли он и приостановлен). Один экземпляр этой структуры выделяется в функции probe
драйвера через kzalloc
, то есть по одному на устройство LCD, и сохраняется в платформенном устройстве, представляющем LCD, используя platform_set_drvdata
. Экземпляр, который был выделен для этого устройства, затем возвращается в начало всех других функций драйвера, чтобы он знал, над каким экземпляром он работает:
struct platform_lcd *plcd = to_our_lcd(lcd);
to_our_lcd
расширяется до lcd_get_data
, который сам расширяется до dev_get_drvdata
(аналог platform_set_drvdata), если вы посмотрите на include/linux/lcd.h
. Затем функция может знать, для какого состояния было вызвано устройство.
Это очень простой пример, и драйвер platform_lcd
не управляет напрямую каким-либо устройством (это откладывается на указатель функции в данных платформы), но добавляет специфичные для оборудования параметры (IRQ, база ввода-вывода, и т.д.), и вы получите, как работают 99% драйверов в Linux.