Рейтинговые книги
Читем онлайн Разработка ядра Linux - Роберт Лав

Шрифт:

-
+

Интервал:

-
+

Закладка:

Сделать
1 ... 103 104 105 106 107 108 109 110 111 ... 132

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().

void kref_get(struct kref *kref) {

 WARN_ON(!atomic_read(&kref->refcount));

 atomic_inc(&kref->refcount);

}

Эта функция увеличивает значение счетчика ссылок на единицу. Она не возвращает никаких значений. Чтобы освободить ссылку на структуру kref, необходимо использовать функцию kref_put().

void kref_put(struct kref *kref, void (*release)(struct kref *kref)) {

 WARN_ON(release == NULL);

 WARN_ON(release == (void(*)(struct kref*))kfree);

 if (atomic_dec_and_test(&kref->refcount))

  release (kref);

}

Эта функция уменьшает значение счетчика ссылок на единицу и вызывает функцию release(), которая передастся ей в качестве параметра, когда значение счетчика ссылок становится равным нулю. Как видно из использованного выражения WARN_ON(), функция release() не может просто совпадать с функцией kfrее(), а должна быть специальной функцией, которая принимает указатель на структуру struct kref в качестве своего единственного параметра и не возвращает никаких значений.

Вместо того чтобы разрабатывать свои функции управления счетчиками ссылок на основании типа данных atomic_t, настоятельно рекомендуется использовать тип данных kref и соответствующие функции, которые обеспечивают общий и правильно работающий механизм поддержки счетчиков ссылок в ядре.

Все эти функции определены в файле lib/kref.c и объявлены в файле <linux/kref.h>.

Файловая система sysfs

Файловая система sysfs — это виртуальная файловая система, которая существует только в оперативной памяти и позволяет просматривать иерархию объектов kobject. Она позволяет пользователям просматривать топологию устройств операционной системы в виде простой файловой системы. Атрибуты объектов kobject могут экспортироваться в виде файлов, которые позволяют считывать значения переменных ядра, а также опционально записывать их.

Хотя изначально целью создания модели представления устройств было описание топологии устройств системы для управления электропитанием, файловая система sysfs стала удачным продолжением этой идеи. Для того чтобы упростить отладку, разработчик унифицированной модели устройств решил экспортировать дерево устройств в виде файловой системы. Такое решение показало свою полезность вначале в качестве замены файлов, связанных с устройствами, которые раньше экспортировались через файловую систему /proc, а позже в качестве мощного инструмента просмотра информации о системной иерархии объектов. Вначале, до появления объектов kobject, файловая система sysfs называлась driverfs. Позже стало ясно — новая объектная модель была бы очень кстати, и в результате этого появилась концепция объектов kobject. Сегодня каждая система, на которой работает ядро 2.6, имеет поддержку файловой системы sysfs, и практически во всех случаях эта файловая система монтируется.

Основная идея работы файловой системы sysfs — это привязка объектов kobject к структуре каталогов с помощью поля dentry, которое есть в структуре kobject. Вспомните из материала главы 12, "Виртуальная файловая система", что структура dentry используется для представления элементов каталогов. Связывание объектов с элементами каталогов проявляется в том, что каждый объект просто видится как каталог файловой системы. Экспортирование объектов kobject в виде файловой системы выполняется путем построения дерева элементов каталогов в оперативной памяти. Но обратите внимание, объекты kobject уже образуют древовидную структуру — нашу модель устройств! Поэтому простое назначение каждому объекту иерархии, которые уже образуют дерево в памяти, соответствующего элемента каталога позволяет легко построить файловую систему sysfs.

На рис. 17.2 показан частичный вид файловой системы sysfs, которая смонтирована на каталог /sys.

Рис. 17.2. Содержимое части каталога /sys

Корневой каталог файловой системы sysfs содержит семь подкаталогов: block, bus, class, devices, firmware, module и power. В каталоге block содержатся каталоги для каждого зарегистрированного в системе устройства блочного ввода-вывода.

Каждый из каталогов в свою очередь содержит подкаталоги, соответствующие разделам блочного устройства. Каталог bus позволяет просматривать информацию о системных шинах. В каталоге class представлена информация о системных устройствах, которая организована в соответствии с высокоуровневыми функциями этих устройств. Каталог devices содержит информацию о топологии устройств в системе. Она отображается непосредственно на иерархию структур устройств ядра. Каталог firmware содержит специфичное для данной системы дерево низкоуровневых подсистем, таких как ACPI, EDD, EFT и т.д. В каталоге power содержатся данные по управлению электропитанием всех устройств системы.

1 ... 103 104 105 106 107 108 109 110 111 ... 132
На этой странице вы можете бесплатно читать книгу Разработка ядра Linux - Роберт Лав бесплатно.
Похожие на Разработка ядра Linux - Роберт Лав книги

Оставить комментарий