Подсистемы соответствуют большим участкам ядра и являются набором множеств kset. Подсистемы представляются с помощью структур struct subsystem. Все каталоги, которые находятся в корне файловой системы sysfs, соответствуют подсистемам ядра.
На рис. 17.1 показаны взаимоотношения между этими структурами данных.
Рис. 17.1. Взаимоотношения между объектами kobject, множествами ksetи подсистемами
Управление и манипуляции с объектами kobject
Теперь, когда у нас уже есть представление о внутреннем устройстве объектов kobjectи связанных с ними структурах данных, самое время рассмотреть экспортируемые интерфейсы, которые дают возможность управлять объектами kobjectи выполнять с ними другие манипуляции. В основном, разработчикам драйверов непосредственно не приходится иметь дело с объектами kobject. Структуры kobjectвстраиваются в некоторые специальные структуры данных (как это было в примере структуры устройства посимвольного ввода-вывода) и управляются "за кадром" с помощью соответствующей подсистемы драйверов. Тем не менее, объекты kobjectне всегда могут оставаться невидимыми, иногда с ними приходится иметь дело, как при разработке кода драйверов, так и при разработке кода управления подсистемами ядра.
Первый шаг при работе с объектами kobject— это их декларация и инициализация. Инициализируются объекты kobjectс помощью функции kobject_init(), которая определена в файле следующим образом.
void kobject_init(struct kobject *kobj);
Единственным параметром этой функции является объект kobject, который необходимо проинициализировать. Перед вызовом этой функции область памяти, в которой хранится объект, должна быть заполнена нулевыми значениями. Обычно это делается при инициализации большой структуры данных, в которую встраивается объект kobject. В других случаях просто необходимо вызвать функцию memset().
memset(kobj, 0, sizeof(*kobj));
После заполнения нулями безопасным будет инициализация полей parentи kset, как показано в следующем примере.
kobj = kmalloc(sizeof(*kobj), GFP_KERNEL);
if (!kobj)
return -ENOMEM;
memset(kobj, 0, sizeof(*kobj));
kobj->kset = kset;
kobj->parent = parent_kobj;
kobject_init(kobj);
После инициализации необходимо установить имя объекта с помощью функции kobject_set_name(), которая имеет следующий прототип.
int kobject_set_name(struct kobject* kobj,
const char* fmt, ...);
Эта функция принимает переменное количество параметров, по аналогии с функциями printf()и printk(). Как уже было сказано, на имя объекта указывает поле k_nameструктуры kobject. Если это имя достаточно короткое, то оно хранится в статически выделенном массиве name, поэтому есть смысл без необходимости не указывать длинные имена.
После того как для объекта выделена память и объекту присвоено имя, нужно установить значение его поля kset, а также опционально поле ktype. Последнее необходимо делать только в том случае, если множество ksetне предоставляет типа ktypeдля данного объекта, в противном случае значение поля ktype, которое указано в структуре kset, имеет преимущество. Если интересно, почему объекты kobjectимеют свое поле ktype, то добро пожаловать в клуб!
Одно из главных свойств, которое реализуется с помощью объектов kobject, — это унифицированная система поддержки счетчиков ссылок. После инициализации количество ссылок на объект устанавливается равным единице. Пока значение счетчика ссылок на объект не равно нулю, объект существует в памяти, и говорят, что он захвачен ( pinned , буквально, пришпилен). Любой код, который работает с объектом, вначале должен увеличить значение счетчика ссылок. После того как код закончил работу с объектом, он должен уменьшить значение счетчика ссылок. Увеличение значения счетчика называют захватом ( getting ), уменьшение — освобождением ( putting ) ссылки на объект. Когда значение счетчика становится равным нулю, объект может быть уничтожен, а занимаемая им память освобождена.
Увеличение значения счетчика ссылок выполняется с помощью функции kobject_get().
struct kobject* kobject_get(struct kobject *kobj);
Эта функция возвращает указатель на объект kobjectв случае успеха и значение NULLв случае ошибки.
Читать дальше