API определен в заголовочном файле sysroot-*-kos/include/kos/init_fini.h из состава KasperskyOS SDK.
API позволяет задать последовательность шагов инициализации/финализации, которая будет выполнена в прямом порядке при инициализации и в обратном порядке при финализации, например, при запуске и завершении программы. Эта последовательность шагов представляет собой массив структур, которые наряду с другими полями содержат поля для идентификаторов callback-функций инициализации и финализации. То есть шаг – это структура, которая содержит идентификатор callback-функции инициализации и/или идентификатор callback-функции финализации. Инициализация осуществляется вызовами callback-функций инициализации при перечислении шагов в порядке возрастания их индексов в массиве. Финализация осуществляется вызовами callback-функций финализации при перечислении шагов в порядке убывания их индексов в массиве. Если при вызове callback-функции инициализации на шаге i произошла ошибка, то дальнейшая инициализация не выполняется, и, начиная с шага i-1, выполняется финализация, чтобы отменить часть инициализации, которая успешно выполнена до возникновения ошибки. Если при вызове callback-функции финализации произошла ошибка, то дальнейшая финализация не выполняется.
Запуск инициализации и финализации реализован потокобезопасно.
Сведения о макросах API приведены в таблице ниже.
Создание последовательности шагов инициализации/финализации
Чтобы создать последовательность шагов инициализации/финализации, нужно использовать макросы KOS_STEPS_COUNT_DECL_BEGIN(), KOS_APPEND_STEP_EX()/KOS_APPEND_STEP() и KOS_STEPS_DECL_END.
Пример:
/* Создание последовательности шагов инициализации/финализации с именем Client.
* Это имя должно быть уникальным в рамках единицы трансляции. */
KOS_STEPS_COUNT_DECL_BEGIN(Client)
KOS_APPEND_STEP_EX("Transport", RTL_NULL, TransportInit, RTL_NULL, RTL_NULL, 0)
KOS_APPEND_STEP("Client objects", ClientObjInit, ClientObjFini)
KOS_APPEND_STEP("Group subscription objects", GroupSubscrObjInit, GroupSubscrObjFini)
KOS_APPEND_STEP("Group publication objects", GroupPubObjInit, GroupPubObjFini)
KOS_APPEND_STEP("Initialization flag", InitializationFlagSet, InitializationFlagReset)
KOS_STEPS_DECL_END
В файле исходного кода конструкцию создания последовательности шагов инициализации/финализации нужно поместить в участок глобальной области видимости (вне определений функций), где доступны callback-функции инициализации и финализации, а также данные, которые будут переданы этим callback-функциями через параметры _init_ctx_ и _fini_ctx_ макроса KOS_APPEND_STEP_EX().
Макросы KOS_STEPS_COUNT_DECL_BEGIN() и KOS_STEPS_DECL_END декларируют соответственно начало и окончание последовательности шагов инициализации/финализации.
Макросы KOS_APPEND_STEP_EX() и KOS_APPEND_STEP() декларируют шаг инициализации/финализации. Используя эти макросы, можно добавить в последовательность шаг, на котором будет выполняться инициализация и симметричная финализация, то есть в параметре _init_cb_ указать идентификатор callback-функции инициализации, а в параметр _fini_cb_ указать идентификатор симметричной callback-функции финализации. Также, например, можно добавить в последовательность шаг, на котором будет выполняться только финализация, то есть в параметре _init_cb_ указать RTL_NULL, а в параметр _fini_cb_ указать идентификатор callback-функции финализации, которая является симметричной по отношению к нескольким callback-функциям инициализации, заданными последующими декларациями шагов.
Макрос KOS_APPEND_STEP_EX() является расширенной версией макроса KOS_APPEND_STEP(), которая позволяет задать не только callback-функции инициализации и финализации (параметры _init_cb_ и _fini_cb_), но и данные, которые будут переданы этим callback-функциям (параметры _init_ctx_ и _fini_ctx_). Также макрос KOS_APPEND_STEP_EX() позволяет задать, нужно ли выполнять журналирование ошибок callback-функции инициализации на декларируемом шаге (параметр _err_verbosity_). При использовании макроса KOS_APPEND_STEP() журналирование ошибок callback-функции инициализации на декларируемом шаге выполняется всегда.
Через параметр _step_name_ макросов KOS_APPEND_STEP_EX() и KOS_APPEND_STEP() можно задать имя шага инициализации/финализации, чтобы данные журналирования ошибок содержали имя этого шага. Если этого не сделать, то декларируемый шаг в данных журналирования ошибок можно будет идентифицировать только по номеру. Нумерация шагов начинается с нуля и соответствует порядку, в котором шаги декларированы. В примере шаг с именем Transport имеет номер 0, шаг с именем Client objects имеет номер 1, шаг с именем Group subscription objects имеет номер 2.
Callback-функции инициализации и финализации для макросов KOS_APPEND_STEP_EX() и KOS_APPEND_STEP() имеют разные сигнатуры. Сигнатура callback-функции инициализации для макроса KOS_APPEND_STEP_EX() соответствует типу KosInitItInitCallback. Эта callback-функция принимает через свой параметр context произвольные данные, заданные через параметр _init_ctx_ макроса KOS_APPEND_STEP_EX(). В случае успеха возвращает rcOk, иначе возвращает код ошибки. Сигнатура callback-функции финализации для макроса KOS_APPEND_STEP_EX() соответствует типу KosInitItFiniCallback. Эта callback-функция принимает через свой параметр context произвольные данные, заданные через параметр _fini_ctx_ макроса KOS_APPEND_STEP_EX(), а также принимает через свой параметр stepType тип финализации (KosInitItStepFini – штатная финализация, KosInitItStepRollBack – финализация в результате ошибки callback-функции инициализации или отмены инициализации). В случае успеха возвращает rcOk, иначе возвращает код ошибки. Сигнатура callback-функций инициализации и финализации для макроса KOS_APPEND_STEP() соответствует типу KosInitItStepCallback. Эти callback-функции не имеют параметров. В случае успеха возвращают rcOk, иначе возвращают код ошибки.
Отмена инициализации
Используя макрос KOS_SET_INIT_CANCEL_CALLBACK(), можно задать для последовательности шагов инициализации/финализации callback-функцию отмены инициализации. Сигнатура этой callback-функции соответствует типу KosInitItCancelCallback. Callback-функция отмены инициализации вызывается на каждом шаге при инициализации и принимает номер этого шага через параметр stepIndx. Если callback-функция отмены инициализации возвращает rtl_true на шаге i, то callback-функция инициализации, соответствующая шагу i, не вызывается, и, начиная с шага i-1 выполняется финализация. Если callback-функция отмены инициализации возвращает rtl_false на шаге i, то callback-функция инициализации, соответствующая шагу i, вызывается, и в случае успешного завершения callback-функции инициализации осуществляется переход на шаг i+1.
Используя callback-функцию отмены инициализации, можно контролировать выполнение каких-либо условий при инициализации. Например, можно контролировать длительность выполнения шагов и отменить инициализацию, если ее длительность превышена. Также использование этой callback-функции дает возможность выполнить какие-либо подготовительные операции перед вызовом callback-функции инициализации на конкретном шаге.
Макрос KOS_SET_INIT_CANCEL_CALLBACK() имеет значение, которое представляет собой идентификатор предыдущей callback-функции отмены инициализации. Сохранение этого значения дает возможность использовать в дальнейшем предыдущую callback-функцию отмены инициализации.
Определения функций, использующих макрос KOS_SET_INIT_CANCEL_CALLBACK(), должны располагаться в файле исходного кода после конструкции создания последовательности шагов инициализации/финализации.
Журналирование ошибок
Если callback-функция инициализации или финализации на шаге завершается с ошибкой, то по умолчанию сообщение об этой ошибке помещается в диагностический вывод. (При использовании макроса KOS_APPEND_STEP_EX() можно отменить журналирование ошибок callback-функции инициализации на декларируемом шаге.) Это сообщение содержит имя последовательности шагов инициализации/финализации, имя или номер шага (в зависимости от того, задано ли имя при декларировании шага), тип процедуры (init – инициализация, fini – штатная финализация, rollback – финализация в результате ошибки callback-функции инициализации или отмены инициализации), сведения об ошибке.
Вместо способа по умолчанию можно использовать собственный способ журналирования ошибок. Для этого нужно с помощью макроса KOS_SET_LOGGER_CALLBACK() задать для последовательности шагов инициализации/финализации собственную callback-функцию журналирования ошибок. Эта callback-функция вызывается, если callback-функция инициализации или финализации на шаге завершается с ошибкой. (При использовании макроса KOS_APPEND_STEP_EX() можно отменить журналирование ошибок callback-функции инициализации на декларируемом шаге.) Сигнатура callback-функции журналирования ошибок соответствует типу KosInitItErrorLoggerCallback. Callback-функция журналирования ошибок принимает имя последовательности инициализации/финализации (параметр subsystemName), номер шага (параметр failedStep), имя шага (если задано при декларировании шага, параметр stepName), код ошибки (параметр rc) и тип процедуры (параметр stepType, который принимает следующие значения: KosInitItStepInit – инициализация, KosInitItStepFini – штатная финализация, KosInitItStepRollBack – финализация в результате ошибки callback-функции инициализации или отмены инициализации). Не возвращает значений. Реализация этой callback-функции может, например, записывать сведения об ошибках в буфер, вместо того чтобы помещать в диагностический вывод.
Макрос KOS_SET_LOGGER_CALLBACK() имеет значение, которое представляет собой идентификатор предыдущей callback-функции журналирования ошибок. Сохранение этого значения дает возможность использовать в дальнейшем предыдущую callback-функцию журналирования ошибок.
Определения функций, использующих макрос KOS_SET_LOGGER_CALLBACK(), должны располагаться в файле исходного кода после конструкции создания последовательности шагов инициализации/финализации.
Запуск инициализации и финализации
Чтобы запустить инициализацию по заданной последовательности шагов инициализации/финализации, нужно использовать макрос KOS_RUN_INIT_STEPS(). Если callback-функции инициализации на всех шагах завершились успешно, макрос имеет значение rcOk. Если callback-функция инициализации на одном из шагов завершилась с ошибкой, макрос имеет значение кода этой ошибки. Если инициализация была отменена, макрос имеет значение rcAbort.
Чтобы запустить финализацию по заданной последовательности шагов инициализации/финализации, нужно использовать макрос KOS_RUN_FINI_STEPS(). Если callback-функции финализации на всех шагах завершились успешно, макрос имеет значение rcOk. Если callback-функция финализации на одном из шагов завершилась с ошибкой, макрос имеет значение кода этой ошибки.
Пример запуска инициализации и финализации:
int main(void)
{
int ret = -1;
INFO(UARTSR, "UART server start");
if (KOS_RUN_INIT_STEPS(UART) == rcOk)
{
KosEventWait(&shutdownEvent, rtl_false);
KOS_RUN_FINI_STEPS(UART);
ret = 0;
}
INFO(UARTSR, "UART server stop");
return ret;
}
Инициализацию по одной и той же последовательности шагов инициализации/финализации можно запускать в нескольких параллельных потоках исполнения, но фактически инициализация будет выполнена один раз. Это относится и к финализации. При этом нужно обеспечить, чтобы число успешных запусков инициализации (когда макрос KOS_RUN_INIT_STEPS() имеет значение rcOk) было равно числу успешных запусков финализации (когда макрос KOS_RUN_FINI_STEPS() имеет значение rcOk). Это обусловлено тем, что первый успешный запуск инициализации выполняет инициализацию в действительности и инкрементирует счетчик запусков инициализации, а последующие успешные запуски инициализации только инкрементируют этот счетчик. При этом успешный запуск финализации декрементирует счетчик запусков инициализации и в действительности не выполняет финализацию, пока этот счетчик не примет значение, которое имел до первого успешного запуска инициализации.
Определения функций, использующих макросы KOS_RUN_INIT_STEPS() и KOS_RUN_FINI_STEPS(), должны располагаться в файле исходного кода после конструкции создания последовательности шагов инициализации/финализации.
Сведения о макросах API
Макросы init_fini.h
Макрос |
Сведения о макросе |
|---|---|
|
Назначение Декларирует начало последовательности шагов инициализации/финализации. Параметры
Значения макроса Нет. |
|
Назначение Декларирует шаг в последовательности шагов инициализации/финализации. Параметры
Значения макроса Нет. |
|
Назначение Декларирует окончание последовательности шагов инициализации/финализации. Параметры Нет. Значения макроса Нет. |
|
Назначение Декларирует шаг в последовательности шагов инициализации/финализации. Параметры
Значения макроса Нет. |
|
Назначение Задает callback-функцию отмены инициализации. Параметры
Значения макроса Идентификатор предыдущей callback-функции отмены инициализации или |
|
Назначение Задает callback-функцию журналирования ошибок. Параметры
Значения макроса Идентификатор предыдущей callback-функции журналирования ошибок или |
|
Назначение Запускает инициализацию по заданной последовательности шагов инициализации/финализации. Параметры
Значения макроса В случае успеха имеет значение |
|
Назначение Запускает финализацию по заданной последовательности шагов инициализации/финализации. Параметры
Значения макроса В случае успеха имеет значение |