diff options
Diffstat (limited to 'documentation/content/ru/books/arch-handbook/kobj/_index.adoc')
| -rw-r--r-- | documentation/content/ru/books/arch-handbook/kobj/_index.adoc | 259 |
1 files changed, 259 insertions, 0 deletions
diff --git a/documentation/content/ru/books/arch-handbook/kobj/_index.adoc b/documentation/content/ru/books/arch-handbook/kobj/_index.adoc new file mode 100644 index 0000000000..fa43b32738 --- /dev/null +++ b/documentation/content/ru/books/arch-handbook/kobj/_index.adoc @@ -0,0 +1,259 @@ +--- +description: 'Объекты ядра' +next: books/arch-handbook/jail +params: + path: /books/arch-handbook/kobj/ +prev: books/arch-handbook/locking +showBookMenu: 'true' +tags: ["kernel objects", "kobj", "guide", "FreeBSD"] +title: 'Глава 3. Объекты ядра' +weight: 4 +--- + +[[kernel-objects]] += Объекты ядра +:doctype: book +:toc: macro +:toclevels: 1 +:icons: font +:sectnums: +:sectnumlevels: 6 +:sectnumoffset: 3 +:partnums: +:source-highlighter: rouge +:experimental: +:images-path: books/arch-handbook/ + +ifdef::env-beastie[] +ifdef::backend-html5[] +:imagesdir: ../../../../images/{images-path} +endif::[] +ifndef::book[] +include::shared/authors.adoc[] +include::shared/mirrors.adoc[] +include::shared/releases.adoc[] +include::shared/attributes/attributes-{{% lang %}}.adoc[] +include::shared/{{% lang %}}/teams.adoc[] +include::shared/{{% lang %}}/mailing-lists.adoc[] +include::shared/{{% lang %}}/urls.adoc[] +toc::[] +endif::[] +ifdef::backend-pdf,backend-epub3[] +include::../../../../../shared/asciidoctor.adoc[] +endif::[] +endif::[] + +ifndef::env-beastie[] +toc::[] +include::../../../../../shared/asciidoctor.adoc[] +endif::[] + +Объекты ядра, или _Kobj_, предоставляют объектно-ориентированную систему программирования на языке C для ядра. Таким образом, данные, с которыми производится работа, содержат описание того, как над ними следует выполнять операции. Это позволяет добавлять и удалять операции из интерфейса во время выполнения без нарушения бинарной совместимости. + +[[kernel-objects-term]] +== Терминология + +Объект:: +Набор данных - структура данных - аллокация данных. + +Метод:: +Операция — функция. + +Класс:: +Один или несколько методов. + +Интерфейс:: +Стандартный набор из одного или нескольких методов. + +[[kernel-objects-operation]] +== Как работает Kobj + +Kobj работает путем генерации описаний методов. Каждое описание содержит уникальный идентификатор, а также функцию по умолчанию. Адрес описания используется для однозначной идентификации метода в таблице методов класса. + +Класс создается путем построения таблицы методов, связывающей одну или несколько функций с описаниями методов. Перед использованием класс компилируется. В процессе компиляции выделяется кэш и связывается с классом. Уникальный идентификатор назначается каждому описанию метода в таблице методов класса, если это еще не было сделано другой ссылающейся компиляцией класса. Для каждого используемого метода скриптом генерируется функция для проверки аргументов и автоматического обращения к описанию метода для поиска. Сгенерированная функция ищет метод, используя уникальный идентификатор, связанный с описанием метода, в качестве хэша для доступа к кэшу, связанному с классом объекта. Если метод не найден в кэше, сгенерированная функция использует таблицу класса для поиска метода. Если метод найден, используется связанная с ним функция внутри класса; в противном случае используется функция по умолчанию, связанная с описанием метода. + +Эти перенаправления можно визуализировать следующим образом: + +[.programlisting] +.... +object->cache<->class +.... + +[[kernel-objects-using]] +== Использование Kobj + +=== Структуры + +[.programlisting] +.... +struct kobj_method +.... + +=== Функции + +[.programlisting] +.... +void kobj_class_compile(kobj_class_t cls); +void kobj_class_compile_static(kobj_class_t cls, kobj_ops_t ops); +void kobj_class_free(kobj_class_t cls); +kobj_t kobj_create(kobj_class_t cls, struct malloc_type *mtype, int mflags); +void kobj_init(kobj_t obj, kobj_class_t cls); +void kobj_delete(kobj_t obj, struct malloc_type *mtype); +.... + +=== Макросы + +[.programlisting] +.... +KOBJ_CLASS_FIELDS +KOBJ_FIELDS +DEFINE_CLASS(name, methods, size) +KOBJMETHOD(NAME, FUNC) +.... + +=== Заголовки + +[.programlisting] +.... +<sys/param.h> +<sys/kobj.h> +.... + +=== Создание шаблона интерфейса + +Первым шагом в использовании Kobj является создание интерфейса. Создание интерфейса включает в себя создание шаблона, который скрипт [.filename]#src/sys/kern/makeobjops.pl# может использовать для генерации заголовочного файла и кода объявлений методов и функций поиска методов. + +В этом шаблоне используются следующие ключевые слова: `#include`, `INTERFACE`, `CODE`, `EPILOG`, `HEADER`, `METHOD`, `PROLOG`, `STATICMETHOD` и `DEFAULT`. + +Включение директивы `#include` и всего, что следует за ней, копируется дословно в начало сгенерированного файла с кодом. + +Например: + +[.programlisting] +.... +#include <sys/foo.h> +.... + +Ключевое слово `INTERFACE` используется для определения имени интерфейса. Это имя объединяется с каждым именем метода в формате [имя интерфейса]_[имя метода]. Его синтаксис: `INTERFACE [имя интерфейса];`. + +Например: + +[.programlisting] +.... +INTERFACE foo; +.... + +Ключевое слово `CODE` копирует свои аргументы дословно в файл кода. Его синтаксис: `CODE { [что угодно] };` + +Например: + +[.programlisting] +.... +CODE { + struct foo * foo_alloc_null(struct bar *) + { + return NULL; + } +}; +.... + +Ключевое слово `HEADER` копирует свои аргументы в заголовочный файл без изменений. Его синтаксис: `HEADER { [что угодно] };` + +Например: + +[.programlisting] +.... +HEADER { + struct mumble; + struct grumble; +}; +.... + +Ключевое слово `METHOD` описывает метод. Его синтаксис: `METHOD [возвращаемый тип] [имя метода] { [объект [, аргументы]] };` + +Например: + +[.programlisting] +.... +METHOD int bar { + struct object *; + struct foo *; + struct bar; +}; +.... + +Ключевое слово `DEFAULT` может следовать за ключевым словом `METHOD`. Оно расширяет ключевое слово `METHOD`, включая функцию по умолчанию для метода. Расширенный синтаксис выглядит так: `METHOD [тип возвращаемого значения] [имя метода] { [объект; [другие аргументы]] } DEFAULT [функция по умолчанию];` + +Например: + +[.programlisting] +.... +METHOD int bar { + struct object *; + struct foo *; + int bar; +} DEFAULT foo_hack; +.... + +Ключевое слово `STATICMETHOD` используется аналогично ключевому слову `METHOD`, за исключением того, что данные kobj не находятся в начале структуры объекта, поэтому приведение к типу kobj_t было бы некорректным. Вместо этого `STATICMETHOD` полагается на то, что данные Kobj указаны как 'ops'. Это также полезно для вызова методов напрямую из таблицы методов класса. + +Ключевые слова `PROLOG` и `EPILOG` вставляют код непосредственно перед или сразу после `METHOD`, к которому они прикреплены. Эта функция в основном используется для профилирования в ситуациях, когда сложно получить информацию другим способом. + +Другие полные примеры: + +[.programlisting] +.... +src/sys/kern/bus_if.m +src/sys/kern/device_if.m +.... + +=== Создание класса + +Второй шаг в использовании Kobj — это создание класса. Класс состоит из имени, таблицы методов и размера объектов, если используются средства обработки объектов Kobj. Для создания класса используйте макрос `DEFINE_CLASS()`. Чтобы создать таблицу методов, создайте массив элементов kobj_method_t, завершающийся записью NULL. Каждую не-NULL запись можно создать с помощью макроса `KOBJMETHOD()`. + +Например: + +[.programlisting] +.... +DEFINE_CLASS(fooclass, foomethods, sizeof(struct foodata)); + +kobj_method_t foomethods[] = { + KOBJMETHOD(bar_doo, foo_doo), + KOBJMETHOD(bar_foo, foo_foo), + { NULL, NULL} +}; +.... + +Класс должен быть "скомпилирован". В зависимости от состояния системы на момент инициализации класса, необходимо использовать статически выделенный кэш, "таблицу операций". Это может быть достигнуто путем объявления `struct kobj_ops` и использования `kobj_class_compile_static();` в противном случае следует использовать `kobj_class_compile()`. + +=== Создание объекта + +Третий шаг в использовании Kobj связан с определением объекта. Процедуры создания объекта Kobj предполагают, что данные Kobj находятся в начале объекта. Если это не подходит, вам придется самостоятельно выделить память для объекта, а затем использовать `kobj_init()` для части объекта, относящейся к Kobj; в противном случае вы можете использовать `kobj_create()` для автоматического выделения и инициализации части объекта, относящейся к Kobj. `kobj_init()` также может использоваться для изменения класса, который использует объект. + +Для интеграции Kobj в объект следует использовать макрос `KOBJ_FIELDS`. + +Например + +[.programlisting] +.... +struct foo_data { + KOBJ_FIELDS; + foo_foo; + foo_bar; +}; +.... + +=== Вызов методов + +Последним шагом в использовании Kobj является простое использование сгенерированных функций для вызова нужного метода в классе объекта. Это так же просто, как использование имени интерфейса и имени метода с небольшими изменениями. Имя интерфейса должно быть соединено с именем метода с использованием символа '_' между ними, все в верхнем регистре. + +Например, если имя интерфейса было foo, а метод — bar, то вызов будет выглядеть следующим образом: + +[.programlisting] +.... +[return value = ] FOO_BAR(object [, other parameters]); +.... + +=== Очистка + +Когда объект, выделенный через `kobj_create()`, больше не нужен, можно вызвать для него `kobj_delete()`, а когда класс больше не используется, можно вызвать для него `kobj_class_free()`. |
