Чтение онлайн

ЖАНРЫ

Разработка ядра Linux (Второе издание)
Шрифт:

С каждым объектом

kobject
связан один определенный тип данных —
ktype
, который представляется с помощью структуры
struct kobj_type
. На экземпляр такой структуры указывает поле
ktype
каждого объекта
kobject
. С помощью типов
ktype
определяются некоторые общие свойства объектов: поведение при удалении объекта, поведение, связанное с файловой системой sysfs, а также атрибуты объекта.

Объекты

kobject
группируются в множества, которые называются
kset
. Множества
kset
представляются с помощью структур данных
struct kset
. Эти множества предназначены для двух целей. Во-первых,
они позволяют использовать встроенный в них объект
kobject
в качестве базового класса для группы других объектов
kobject
. Во-вторых, они позволяют объединять вместе несколько связанных между собой объектов
kobject
. На файловой системе sysfs объекты
kobject
представляются отдельными каталогами файловой системы. Связанные между собой каталоги, например все подкаталоги одного каталога, могут быть включены в одно множество
kset
.

Подсистемы соответствуют большим участкам ядра и являются набором множеств kset. Подсистемы представляются с помощью структур

struct subsystem
. Все каталоги, которые находятся в корне файловой системы sysfs, соответствуют подсистемам ядра.

На рис. 17.1 показаны взаимоотношения между этими структурами данных.

Рис. 17.1. Взаимоотношения между объектами

kobject
, множествами
kset
и подсистемами

Управление и манипуляции с объектами

kobject

Теперь, когда у нас уже есть представление о внутреннем устройстве объектов

kobject
и связанных с ними структурах данных, самое время рассмотреть экспортируемые интерфейсы, которые дают возможность управлять объектами
kobject
и выполнять с ними другие манипуляции. В основном, разработчикам драйверов непосредственно не приходится иметь дело с объектами
kobject
. Структуры
kobject
встраиваются в некоторые специальные структуры данных (как это было в примере структуры устройства посимвольного ввода-вывода) и управляются "за кадром" с помощью соответствующей подсистемы драйверов. Тем не менее, объекты
kobject
не всегда могут оставаться невидимыми, иногда с ними приходится иметь дело, как при разработке кода драйверов, так и при разработке кода управления подсистемами ядра.

Первый шаг при работе с объектами

kobject
— это их декларация и инициализация. Инициализируются объекты
kobject
с помощью функции
kobject_init
, которая определена в файле
<linux/kobject.h>
следующим образом.

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
в случае ошибки.

Уменьшение значения счетчика ссылок выполняется с помощью функции

kobject_put
.

void kobject put(struct kobject *kobj);

Если значение счетчика ссылок объекта, который передается в качестве параметра, становится равным нулю, то вызывается функция, на которую указывает указатель

release
поля
ktype
этого объекта.

Структуры

kref

Внутреннее представление счетчика ссылок выполнено с помощью структуры

kref
, которая определена в файле
<linux/kref.h>
следующим образом.

struct kref {

 atomic_t refcount;

};

Единственное поле этой структуры — атомарная переменная, в которой хранится значение счетчика ссылок. Структура используется просто для того, чтобы выполнять проверку типов. Чтобы воспользоваться структурой

kref
, необходимо ее инициализировать с помощью функции
kref_init
.

void kref_init(struct kref *kref) {

 atomic_set(&kref->refcount, 1);

}

Как видно из определения, эта функция просто инициализирует атомарную переменную тина

atomic_t
в значение, равное единице.

Следовательно, структура

kref
является захваченной сразу же после инициализации, так же ведут себя и объекты
kobject
.

Для того чтобы захватить ссылку на структуру

kref
, необходимо использовать функцию
kref_get
.

Поделиться с друзьями: