Коды возврата
В решении на базе KasperskyOS для кодирования результатов выполнения функций API используется несколько разных типов кодов возврата. Почти все функции API библиотеки libkos, передающие коды возврата, возвращают значения типа Retcode, который определен в заголовочном файле sysroot-*-kos/include/rtl/retcode.h из состава KasperskyOS SDK. Также коды возврата этого типа передаются функциями API библиотеки kdf и функциями API программ, поставляемых в составе KasperskyOS SDK (например, драйверов и других системных программ, созданных для использования в решениях на базе KasperskyOS). Функции транспортного кода, несколько функций API библиотеки libkos для работы с IPC-транспортом и функции некоторых других API, связанных с IPC (например, функции, определенные в заголовочном файле sysroot-*-kos/include/nk/transport.h из состава KasperskyOS SDK), передают коды возврата типа nk_err_t, который определен в заголовочном файле sysroot-*-kos/include/nk/types.h из состава KasperskyOS SDK. Функции интерфейса POSIX и функции API стороннего ПО передают коды возврата других типов.
Разработчику решения рекомендуется кодировать результаты выполнения своих функций, используя коды возврата типа Retcode.
Формат кода возврата типа Retcode
Тип Retcode определен в заголовочном файле retcode.h как 32-битное знаковое целое число:
typedef __INT32_TYPE__ Retcode;
Множество кодов возврата типа Retcode состоит из кода успеха со значением 0 и кодов ошибок. Код ошибки интерпретируется как структура данных, формат которой показан на рисунке ниже.
Формат кода возврата типа Retcode
Этот формат предусматривает наличие нескольких полей, которые содержат не только сведения о результатах выполнения функции (в поле Code), но и следующую дополнительную информацию:
- Флаг в поле
Severity, отличающий код ошибки (1) от кода успеха (0). Это поле используется для обратной совместимости с другими форматами кодов ошибок. - Флаг в поле
Customer, сигнализирующий о том, что код ошибки определен разработчиками решения, а не разработчиками ПО из состава KasperskyOS SDK.Благодаря флагу в поле
Customerразработчики решения и разработчики ПО из состава KasperskyOS SDK могут определять коды ошибок из непересекающихся множеств. - Глобальный идентификатор кода ошибки в поле
Space.Глобальные идентификаторы позволяют определять непересекающиеся множества кодов ошибок. Коды ошибок могут быть общими и специфичными. Общие коды ошибок могут использоваться в API любых компонентов решения и в API любых составных частей компонентов решения (например, драйвер или VFS могут быть составной частью компонента решения). Специфичные коды ошибок используются в API одного или нескольких компонентов решения или в API одной или нескольких составных частей компонентов решения.
Например, идентификатору
RC_SPACE_GENERALсоответствуют коды общих ошибок, идентификаторуRC_SPACE_KERNELсоответствуют коды ошибок ядра, идентификаторуRC_SPACE_DRIVERSсоответствуют коды ошибок драйверов. - Локальный идентификатор кода ошибки в поле
Facility.Локальные идентификаторы позволяют определять непересекающиеся подмножества кодов ошибок в рамках множества кодов ошибок, которые соответствуют одному глобальному идентификатору. Например, множество кодов ошибок с глобальным идентификатором
RC_SPACE_DRIVERSвключает непересекающиеся подмножества кодов ошибок с локальными идентификаторамиRC_FACILITY_I2C,RC_FACILITY_USB,RC_FACILITY_BLKDEV. (Эти локальные идентификаторы определены в заголовочном файлеsysroot-*-kos/include/kdf/facilities.hиз состава KasperskyOS SDK.)
Глобальные и локальные идентификаторы специфичных кодов ошибок назначаются разработчиками решения и разработчиками ПО из состава KasperskyOS SDK независимо друг от друга. То есть формируется два множества глобальных идентификаторов. Каждый глобальный идентификатор имеет уникальное смысловое значение в рамках одного множества. Каждый локальный идентификатор имеет уникальное смысловое значение в рамках множества локальных идентификаторов, относящихся к одному глобальному идентификатору.
Такой централизованный подход позволяет избежать появления в решении одинаковых кодов ошибок с разными смысловыми значениями. Это нужно, чтобы исключить проблему транзита кодов ошибок через разные API. Например, такая проблема возникает, когда драйверы вызывают функции библиотеки kdf, получают коды ошибок и возвращают эти коды через свои API. Если формировать коды ошибок без централизованного подхода, то один и тот же код ошибки может иметь разные смысловые значения для библиотеки kdf и для драйвера. В таких условиях драйверы возвращают корректные коды ошибок, если только выполняется преобразование кодов ошибок библиотеки kdf в коды ошибок каждого из драйверов. То есть коды ошибок назначаются так, чтобы не выполнять конвертацию этих кодов при транзите через разные API.
Общие коды возврата типа Retcode
Общие коды возврата типа Retcode, которые определены в заголовочном файле retcode.h, приведены в таблице ниже. Также в этой таблице показано соответствие между кодами возврата типа Retcode и кодами возврата типа nk_err_t, которые определены в заголовочном файле sysroot-*-kos/include/nk/errno.h из состава KasperskyOS SDK. Сведения об этом соответствии требуются, чтобы конвертировать коды возврата этих двух типов между собой. Например, конвертация нужна, если разрабатываемая функция, которая возвращает значения типа Retcode, "оборачивает" функцию транспортного кода, которая возвращает значения типа nk_err_t. При этом следует учитывать, что конвертация возможна не всегда по следующим причинам:
- Часть кодов возврата не отображается на коды возврата другого типа.
- Некоторым кодам возврата типа
nk_err_tсоответствует несколько кодов возврата типаRetcode, то есть невозможно однозначно определить, какому именно коду возврата типаRetcodeсоответствует код возврата типаnk_err_t, который требуется конвертировать.Общие коды возврата типа Retcode
Код возврата типа Retcode
Описание
Код возврата типа nk_err_t
rcOk(соответствует значению0)Функция завершилась успешно.
NK_EOKrcInvalidArgumentПараметр функции некорректен.
NK_EINVALrcNotConnectedНет соединения между клиентской и серверной сторонами взаимодействия.
Например, отсутствует серверный IPC-дескриптор.
NK_ENOTCONNrcOutOfMemoryНедостаточно памяти для выполнения операции.
NK_ENOMEMrcBufferTooSmallНедостаточный размер буфера.
NK_EBADMSGrcInternalErrorФункция завершилась с внутренней ошибкой, которая связана с некорректной логикой.
Примерами внутренних ошибок являются: выход значений за допустимые пределы, появление нулевых указателей и значений там, где этого быть не должно.
Нет
rcTransferErrorОшибка отправки IPC-сообщения.
Нет
rcReceiveErrorОшибка приема IPC-сообщения.
Нет
rcSourceFaultIPC-сообщение не было передано из-за источника IPC-сообщения.
Нет
rcTargetFaultIPC-сообщение не было передано из-за приемника IPC-сообщения.
Нет
rcIpcInterruptIPC прервано другим потоком процесса.
Нет
rcInvalidFormatФормат данных некорректен.
Нет
rcRestartСигнализирует, что функцию нужно вызвать повторно.
Нет
rcFailФункция завершилась с ошибкой.
Нет
rcNoCapabilityОперация с ресурсом недоступна.
NK_ENOENTrcNotReadyИнициализация не выполнена.
NK_EAGAINrcUnimplementedФункция не реализована.
Нет
rcBufferTooLargeБольшой размер буфера.
NK_EBADMSGrcBusyРесурс временно недоступен.
Нет
rcResourceNotFoundРесурс не найден.
Нет
rcTimeoutВремя ожидания истекло.
NK_EAGAINrcSecurityDisallowОперация запрещена механизмами безопасности.
NK_EPERMrcFutexWouldBlockОперация приведет к блокировке.
Нет
rcAbortОперация прервана.
NK_ENOENTrcInvalidThreadStateВ обработчике прерывания вызвана недопустимая функция.
Нет
rcAlreadyExistsМножество элементов уже содержит добавляемый элемент.
NK_ENOTEMPTYrcInvalidOperationОперация не может быть выполнена.
Нет
rcHandleRevokedПрава доступа к ресурсу отозваны.
NK_EREVOKEDrcQuotaExceededКвота на ресурс превышена.
Нет
rcDeviceNotFoundУстройство не найдено.
Нет
rcOverflowПроизошло переполнение.
Нет
rcAlreadyDoneОперация уже выполнена.
Нет
rcNotRunОперация не была запущена.
Нет
rcEntropySourceStuckИсточник энтропии может быть ненадежным.
Нет
rcDeadlockВозникла взаимная блокировка.
Нет
rcInvalidHandleДескриптор закрыт.
Нет
Определение кода ошибки типа Retcode
Чтобы определить код ошибки типа Retcode, разработчику решения нужно использовать макрос MAKE_RETCODE(), определенный в заголовочном файле retcode.h. При этом через параметр customer нужно передать символьную константу RC_CUSTOMER_TRUE.
Пример:
#define LV_EBADREQUEST MAKE_RETCODE(RC_CUSTOMER_TRUE, RC_SPACE_APPS, RC_FACILITY_LogViewer, 5, "Bad request")
Описание ошибки, которое передается через параметр desc, не используется макросом MAKE_RETCODE(). Это описание требуется, чтобы создать базу данных кодов ошибок при сборке решения на базе KasperskyOS. В настоящее время механизм для создания и использования такой базы данных не реализован.
Чтение полей структуры кода ошибки типа Retcode
Макросы RC_GET_CUSTOMER(), RC_GET_SPACE(), RC_GET_FACILITY() и RC_GET_CODE(), определенные в заголовочном файле retcode.h, позволяют читать поля структуры кода ошибки типа Retcode.
Макросы RETCODE_HR_PARAMS() и RETCODE_HR_FMT, определенные в заголовочном файле sysroot-*-kos/include/rtl/retcode_hr.h из состава KasperskyOS SDK, предназначены для форматированного вывода сведений об ошибке типа Retcode.