Использование специальных загружаемых секций ELF-образа с массивами объектов данных (iterable_section.h)

API определен в заголовочном файле sysroot-*-kos/include/kos/iterable_section.h из состава KasperskyOS SDK.

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

Сведения о макросах API приведены в таблице ниже.

Добавление объекта данных в специальную секцию ELF-образа

Чтобы добавить объект данных в специальную секцию ELF-образа, нужно использовать макрос KOS_ITERABLE_SECTION_REGISTER(). Этот макрос добавляет объект данных в специальную секцию того типа, имя которого указано в параметре type. Имя типа специальной секции должно состоять из одного слова. Чтобы задать тип, имя которого состоит из нескольких слов (например, unsigned long, const volatile double), в параметре type нужно указать псевдоним этого типа, созданный с помощью typedef. Можно задать как примитивный, так и составной тип.

Объект данных, добавляемый в специальную секцию, как правило, нужно инициализировать. Технически это не требуется, то есть можно добавить в специальную секцию неинициализированные объекты данных, чтобы потом использовать наряду с другими глобальными переменными или получить число объектов данных в этой специальной секции, но это не является основным назначением API. Основное назначение API заключается в том, чтобы во время сборки программы поместить данные в специальные секции, а во время исполнения программы получить доступ к этим данным.

Пример добавления инициализированного объекта данных в специальную секцию:

typedef struct SFooClientOps

{

Retcode (*init)(void);

void (*fini)(void);

} FooClientOps;

typedef struct SFooClient

{

const FooClientOps *ops;

} FooClient;

static Retcode InitClient(void)

{

...

}

static void FiniClient(void)

{

...

}

static const FooClientOps ops = {

.init = InitClient,

.fini = FiniClient,

};

KOS_ITERABLE_SECTION_REGISTER(FooClient) = {

.ops = &ops

};

Если единица трансляции, в которой используется макрос KOS_ITERABLE_SECTION_REGISTER(), будет включена в программу при сборке, то объект данных будет добавлен в специальную секцию. Если требуемый вариант программы не будет включать эту единицу трансляции, то объект данных не будет добавлен в специальную секцию. Это автоматически обеспечивает соответствие содержимого специальной секции требуемому варианту программы.

В файле исходного кода макрос KOS_ITERABLE_SECTION_REGISTER() нужно поместить в глобальную область видимости.

Открытие доступа к специальной секции ELF-образа

Чтобы открыть доступ к специальной секции ELF-образа, нужно использовать макрос KOS_ITERABLE_SECTION_DECLARE(). Этот макрос открывает доступ к специальной секции того типа, имя которого указано в параметре type. Открытие доступа к специальной секции обеспечивает возможность получить число объектов данных в этой специальной секции, получить доступ к каждому объекту по индексу и выполнить обход объектов.

Макрос KOS_ITERABLE_SECTION_DECLARE() нужно использовать в каждой единице трансляции, в которой требуется получить доступ к специальной секции.

В файле исходного кода макрос KOS_ITERABLE_SECTION_DECLARE() нужно поместить в глобальную область видимости.

Получение числа объектов данных в специальной секции ELF-образа

Чтобы получить число объектов данных в специальной секции ELF-образа, нужно использовать макрос KOS_ITERABLE_SECTION_COUNTOF(). Этот макрос имеет значение, которое соответствует числу объектов данных в специальной секции того типа, имя которого указано в параметре type.

Определения функций, использующих макрос KOS_ITERABLE_SECTION_COUNTOF(), должны располагаться в файле исходного кода после макроса KOS_ITERABLE_SECTION_DECLARE().

Перечисление объектов данных в специальной секции ELF-образа

Чтобы перечислить объекты данных в специальной секции ELF-образа, нужно использовать макрос KOS_ITERABLE_SECTION_ENUM(). Этот макрос перечисляет объекты данных в специальной секции того типа, имя которого указано в параметре type. Имеет значение, которое соответствует указателю на объект данных с индексом, указанным в параметре index.

Определения функций, использующих макрос KOS_ITERABLE_SECTION_ENUM(), должны располагаться в файле исходного кода после макроса KOS_ITERABLE_SECTION_DECLARE().

Обход объектов данных в специальной секции ELF-образа

Чтобы выполнить обход объектов данных в специальной секции ELF-образа, нужно использовать макрос KOS_ITERABLE_SECTION_FOR_EACH() или KOS_ITERABLE_SECTION_FOR_EACH_REVERSE(). Эти макросы выполняют обход объектов данных в специальной секции того типа, имя которого указано в параметре type. Макрос KOS_ITERABLE_SECTION_FOR_EACH() выполняет обход в прямом порядке, а макрос KOS_ITERABLE_SECTION_FOR_EACH_REVERSE() выполняет обход в обратном порядке. Оба макроса раскрываются в заголовок оператора for. Указатель, имя которого указано в параметре iterator, будет содержать адрес очередного объекта данных на каждой итерации.

Пример использования макроса KOS_ITERABLE_SECTION_FOR_EACH():

static Retcode InitDrivers(void)

{

Retcode rc = rcOk;

KOS_ITERABLE_SECTION_FOR_EACH(ExampleDriverClassDriverImpl, driver)

{

rtl_assert(driver->name != RTL_NULL);

rtl_assert(driver->init != RTL_NULL);

rtl_assert(!driver->isInitialized);

rc = driver->init();

if (rc == rcOk)

{

driver->isInitialized = rtl_true;

}

else

{

ERROR(EXAMPLE_CLASS, "Failed to initialize \"%s\" driver", driver->name);

break;

}

}

if (rc != rcOk)

{

FiniDrivers();

}

return rc;

}

Пример использования макроса KOS_ITERABLE_SECTION_FOR_EACH_REVERSE():

static Retcode FiniDrivers(void)

{

KOS_ITERABLE_SECTION_FOR_EACH_REVERSE(ExampleDriverClassDriverImpl, driver)

{

if (driver->isInitialized && driver->fini != RTL_NULL)

{

driver->fini();

driver->isInitialized = rtl_false;

}

}

return rcOk;

}

Определения функций, использующих макросы KOS_ITERABLE_SECTION_FOR_EACH() и KOS_ITERABLE_SECTION_FOR_EACH_REVERSE(), должны располагаться в файле исходного кода после макроса KOS_ITERABLE_SECTION_DECLARE().

Сведения о макросах API

Макросы iterable_section.h

Макрос

Сведения о макросе

KOS_ITERABLE_SECTION_REGISTER()

Назначение

Добавляет объект данных в специальную секцию заданного типа.

Параметры

  • [in] type – имя типа специальной секции.

Значения макроса

Нет.

KOS_ITERABLE_SECTION_DECLARE()

Назначение

Открывает доступ к специальной секции заданного типа.

Параметры

  • [in] type – имя типа специальной секции.

Значения макроса

Нет.

KOS_ITERABLE_SECTION_COUNTOF()

Назначение

Позволяет получить число объектов данных в специальной секции заданного типа.

Параметры

  • [in] type – имя типа специальной секции.

Значения макроса

Число объектов данных в специальной секции заданного типа.

KOS_ITERABLE_SECTION_ENUM()

Назначение

Перечисляет объекты данных в специальной секции заданного типа.

Параметры

  • [in] type – имя типа специальной секции.
  • [in] index – индекс для перечисления объектов данных. Нумерация начинается с нуля.

Значения макроса

Указатель на объект данных в специальной секции заданного типа или RTL_NULL, если индекс вне допустимого диапазона.

KOS_ITERABLE_SECTION_FOR_EACH()

Назначение

Выполняет обход объектов данных в специальной секции заданного типа в прямом порядке.

Параметры

  • [in] type – имя типа специальной секции.
  • [in] iterator – имя указателя для сохранения адресов объектов данных при обходе.

Значения макроса

Нет.

KOS_ITERABLE_SECTION_FOR_EACH_REVERSE()

Назначение

Выполняет обход объектов данных в специальной секции заданного типа в обратном порядке.

Параметры

  • [in] type – имя типа специальной секции.
  • [in] iterator – имя указателя для сохранения адресов объектов данных при обходе.

Значения макроса

Нет.

В начало