Управление процессами (низкоуровневый API task_api.h)
API определен в заголовочном файле sysroot-*-kos/include/coresrv/task/task_api.h
из состава KasperskyOS SDK.
Основные возможности API:
- создавать, запускать и завершать процессы;
- обрабатывать исключения;
- получать сведения о процессах, включая информацию о причинах их завершения;
- задавать приоритеты и классы планирования начальных потоков процессов.
Сведения о функциях API приведены в таблице ниже.
Библиотека libkos
также предоставляет высокоуровневый API для управления процессами, который определен в заголовочном файле sysroot-*-kos/include/kos/task.h
из состава KasperskyOS SDK. Рекомендуется использовать именно этот API. Низкоуровневый API следует использовать, если недостаточно возможностей высокоуровневого API.
Создание и запуск процессов
Чтобы создать процесс, нужно вызвать функцию KnTaskCreate()
или KnTaskCreateEx()
. Эти функции создают "пустой" процесс, то есть процесс, в память которого не загружен ELF-образ программы. Перед запуском такого процесса нужно выполнить следующие шаги:
- Создать начальное значение генератора случайных чисел вызовом функции
KosRandomGenerate()
, которая объявлена в заголовочном файлеsysroot-*-kos/include/kos/random/random_api.h
из состава KasperskyOS SDK.Этот шаг необходим для выполнения следующего шага.
- Задать начальное значение генератора случайных чисел вызовом функции
KnTaskReseedAslr()
.Этот шаг необходим для рандомизации размещения адресного пространства процесса. Рандомизация размещения адресного пространства (англ. Address Space Layout Randomization, ASLR) – это размещение структур данных (ELF-образа, динамических библиотек, стека и кучи) в памяти процесса по случайным адресам с целью усложнения эксплуатации уязвимостей, которые связаны с заранее известной злоумышленнику структурой адресного пространства процесса.
Функция
KnTaskReseedAslr()
задает начальное значение генератора случайных чисел, который используется для автоматического выбора базового адреса выделяемого региона виртуальной памяти в таких функциях, какKnVmAllocate()
,KnPmmMdlMap()
,KnIoDmaMap()
,KnTaskVmReserve()
. Создание стека и кучи в процессе, а также загрузка динамических библиотек в его память выполняются операционной системой с использованием функцииKnVmAllocate()
. При этом в параметреaddr
указывается ноль, чтобы адрес выделенного региона виртуальной памяти был выбран автоматически, то есть был случайным значением. - Стереть из памяти начальное значение генератора случайных чисел, созданное на шаге 1.
Этот шаг необходим для целей безопасности. Чтобы выполнить этот шаг, нужно вызвать функцию
RtlRandomMemSanitize()
, которая объявлена в заголовочном файлеsysroot-*-kos/include/rtl/random.h
из состава KasperskyOS SDK. - Загрузить сегменты ELF-образа в память процесса с использованием функции
KnTaskLoadSeg()
.В поле
loadAddr
параметраseg
нужно указать адрес загрузки сегмента ELF-образа. С целью поддержки ASLR (дополнительно к шагу 2) адрес загрузки сегмента ELF-образа, указанный в ELF-файле, должен быть увеличен на смещение загрузки ELF-образа. Смещение загрузки ELF-образа должно быть случайным значением. Генерацию случайного смещения загрузки ELF-образа и расчет адресов загрузки сегментов ELF-образа с учетом этого смещения выполняет функцияKnElfCreateVmSegEx()
, объявленная в заголовочном файлеsysroot-*-kos/include/coresrv/elf/elf_api.h
из состава KasperskyOS SDK.В результате этого шага буферы MDL, которые содержат сегменты ELF-образа, будут отображены на виртуальную память процесса.
- [Опционально] Загрузить таблицу символов
.symtab
и таблицу строк.strtab
в память процесса вызовом функцииKnTaskLoadElfSyms()
.Адреса загрузки сегментов ELF-образа с таблицей символов
.symtab
и таблицей строк.strtab
должны быть рассчитаны так же, как и адреса загрузки других сегментов ELF-образа. Этот расчет выполняет функцияKnElfCreateVmSegEx()
, объявленная в заголовочном файлеsysroot-*-kos/include/coresrv/elf/elf_api.h
из состава KasperskyOS SDK.Используя таблицу символов
.symtab
и таблицу строк.strtab
, ядро получает имена функций для формирования данных обратной трассировки стека (сведений о стеке вызовов). - Задать точку входа в программу и смещение загрузки ELF-образа вызовом функции
KnTaskSetInitialState()
.Точка входа в программу представляет собой сумму адреса, указанного в поле
e_entry
заголовка ELF-образа, и смещения загрузки ELF-образа. Генерацию случайного смещения загрузки ELF-образа и расчет адреса точки входа в программу с учетом этого смещения выполняет функцияKnElfCreateVmSegEx()
, объявленная в заголовочном файлеsysroot-*-kos/include/coresrv/elf/elf_api.h
из состава KasperskyOS SDK. - [Опционально] Загрузить в память процесса заголовок ELF-образа вызовом функции
KnTaskSetElfHdr()
.Этот шаг нужно выполнить, если требуется, чтобы данные из заголовка ELF-образа были доступны в созданном процессе.
Дескриптор процесса можно передать другому процессу через IPC.
По умолчанию начальный поток процесса является стандартным потоком исполнения, приоритет которого может принимать значения от 0 до 15. (О классах планирования потоков исполнения см. "Управление потоками исполнения (низкоуровневый API thread_api.h)".) Чтобы изменить класс планирования и/или приоритет начального потока процесса, нужно вызвать функцию KnTaskSetInitialPolicy()
. Чтобы изменить приоритет начального потока процесса, нужно вызвать функцию KnTaskSetInitialThreadPriority()
. Функции KnTaskSetInitialPolicy()
и KnTaskSetInitialThreadPriority()
можно использовать после задания точки входа в программу. Также эти функции можно использовать после запуска процесса.
Чтобы запустить процесс, нужно вызвать функцию KnTaskResume()
. Запущенный процесс нельзя приостановить.
Перед запуском процесс получает данные от своего родительского процесса через страницу статических соединений. Страница статических соединений (англ. Static Connection Page, SCP) – набор структур, содержащих данные для статического создания IPC-каналов, параметры запуска и переменные окружения программы. Родительский процесс записывать данные в SCP дочернего процесса вызовом функции KnTaskSetEnv()
. Дочерний процесс при запуске считывает данные из SCP вызовом функции KnTaskGetEnv()
, а затем удаляет SCP вызовом функции KnTaskFreeEnv()
. Все три функции не требуется явно вызывать, так как их вызовы выполняет библиотека libkos
.
Завершение процессов
Завершение процесса включает в себя:
- Завершение всех потоков процесса.
- Освобождение памяти процесса.
- Освобождение системных и пользовательских ресурсов, которыми процесс владеет эксклюзивно.
При завершении процесса все дескрипторы, которыми он владеет, закрываются. Если закрытый дескриптор был единственным дескриптором ресурса, то этот ресурс освобождается.
Процесс завершается по следующим причинам:
- По собственной инициативе.
Вызвана функция
KnTaskExit()
, или завершены все потоки процесса. - По внешнему запросу.
Вызвана функция
KnTaskTerminate()
. - В результате необработанного исключения (аварийно).
Вызовом функции
KnTaskPanic()
процесс может специально инициировать возникновение исключения, которое не может быть обработано и приводит к завершению этого процесса. Это требуется, чтобы процесс мог гарантированно завершить себя. (Например, если в процессе есть потоки исполнения, привязанные к прерываниям, то функцияKnTaskExit()
не может завершить этот процесс, а функцияKnTaskPanic()
позволяет сделать это.)
Коды завершения процессов определяются разработчиком решения на базе KasperskyOS. Эти коды нужно указывать в параметре status
функции KnTaskExit()
. Если процесс завершился в результате завершения всех его потоков, то кодом завершения этого процесса будет код завершения его начального потока. Чтобы получить код завершения процесса, который завершился по собственной инициативе, нужно вызвать функцию KnTaskGetExitCode()
.
Чтобы получить сведения о причине завершения процесса, нужно вызвать функцию KnTaskGetExitStatus()
. Эта функция позволяет определить, был ли процесс завершен по собственной инициативе, по внешнему запросу или аварийно.
Чтобы получить сведения о необработанном исключении, которое привело к аварийному завершению процесса, нужно вызвать функцию KnTaskGetExceptionInfo()
. Эти сведения включают код исключения и контекст потока исполнения, в котором это исключение возникло.
Если процесс создан вызовом функции KnTaskCreateEx()
с флагом TaskExceptionFreezesTask
в параметре flags
, то в результате необработанного исключения этот процесс не завершится, а перейдет в "замороженное" состояние. "Замороженное" состояние процесса – это такое состояние процесса, при котором исполнение его потоков завершилось в результате необработанного исключения, но ресурсы не освободились, чтобы можно было получить сведения об этом процессе. Чтобы получить контекст потока исполнения, входящего в процесс, который находится в "замороженном" состоянии, нужно вызвать функцию KnTaskGetThreadContext()
. Чтобы получить сведения о регионе виртуальной памяти, принадлежащем процессу, который находится в "замороженном" состоянии, нужно вызвать функцию KnTaskGetNextVmRegion()
. Эти сведения включают такую информацию, как базовый адрес и размер региона виртуальной памяти, права доступа к нему. Перед переходом процесса в "замороженное" состояние выполняется вывод данных обратной трассировки стека (сведений о стеке вызовов) для потока исполнения, в котором возникло необработанное исключение. Чтобы завершить процесс, который находится в "замороженном" состоянии, нужно вызвать функцию KnTaskTerminateAfterFreezing()
.
Чтобы объект ядра, который описывает процесс, был удален после завершения этого процесса, нужно до или после завершения этого процесса закрыть или отозвать каждый его дескриптор во всех процессах, которые владеют этими дескрипторами. Чтобы выполнить это, нужно использовать функцию KnHandleClose()
и/или KnHandleRevoke()
, которые объявлены в заголовочном файле sysroot-*-kos/include/coresrv/handle/handle_api.h
из состава KasperskyOS SDK.
Обработка исключений
Чтобы зарегистрировать функцию обработки исключений, нужно вызвать функцию KnTaskSetExceptionHandler()
. Эта функция дерегистрирует предыдущую функцию обработки исключений и возвращает ее идентификатор. Сохранив этот идентификатор, в дальнейшем можно снова зарегистрировать предыдущую функцию обработки исключений.
Функция обработки исключений вызывается при возникновении исключения в любом потоке процесса. В случае успешной обработки исключения эта функция возвращает значение, отличное от ноля, в противном случае она возвращает ноль. Входным параметром функции обработки исключений является структура, содержащая сведения об исключении. Тип этой структуры определен в заголовочном файле sysroot-*-kos/include/thread/tcbpage.h
из состава KasperskyOS SDK.
Если функции обработки исключений, зарегистрированной на уровне процесса, не удалось успешно обработать исключение, будет вызвана функция обработки исключений, зарегистрированная на уровне потока исполнения, в котором возникло это исключение. (Об обработке исключений на уровне потоков исполнения см. "Управление потоками исполнения (низкоуровневый API thread_api.h)".)
Резервирование памяти в дочернем процессе
API включает функции KnTaskVmReserve()
и KnTaskVmFree()
, которые позволяют соответственно резервировать и освобождать регионы виртуальной памяти в дочернем процессе, для которого еще не задана точка входа в программу. Эти функции являются только частью функциональности, нацеленной на повышение уровня контроля родительского процесса за виртуальным адресным пространством дочернего процесса. В настоящее время эта функциональность находится в разработке.
Получение адреса GSI
Общая системная информация (англ. Global System Information, GSI) – структура, содержащая системные сведения, такие как число отсчетов таймера с момента запуска ядра, число отсчетов таймера в секунду, число процессоров (вычислительных ядер) в активном состоянии, данные о процессорном кеше. Тип структуры определен в заголовочном файле sysroot-*-kos/include/task/pcbpage.h
из состава KasperskyOS SDK. Получить адрес GSI позволяет функция KnTaskGetGsi()
. Эта функция предназначена для использования библиотекой libc
.
Получение адреса PCB
Блок управления процессом (англ. Process Control Block, PCB) – структура, содержащая сведения о процессе, которые используются ядром для управления этим процессом. Тип структуры определен в заголовочном файле sysroot-*-kos/include/task/pcbpage.h
из состава KasperskyOS SDK. Получить адрес PCB позволяет функция KnTaskGetPcb()
. Эта функция предназначена для использования библиотекой libc
.
Сведения о функциях API
Функции task_api.h
Функция |
Сведения о функции |
---|---|
|
Назначение Создает процесс. Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Создает процесс. Параметры
Возвращаемые значения В случае успеха возвращает Дополнительные сведения В параметре
|
|
Назначение Позволяет получить адрес GSI для вызывающего процесса. Параметры Нет. Возвращаемые значения Указатель на GSI. Тип данных для хранения GSI определен в заголовочном файле |
|
Назначение Позволяет получить адрес блока управления процессом (PCB) для вызывающего процесса. Параметры Нет. Возвращаемые значения Указатель на PCB. Тип данных для хранения PCB определен в заголовочном файле |
|
Назначение Позволяет получить адрес SCP вызывающего процесса. Параметры
Возвращаемые значения Указатель на SCP или |
|
Назначение Записывает данные в SCP процесса. Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Удаляет SCP вызывающего процесса. Параметры Нет. Возвращаемые значения В случае успеха возвращает |
|
Назначение Записывает заголовок ELF-образа в PCB процесса. Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Запускает процесс. Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Завершает вызывающий процесс. Параметры
Возвращаемые значения Код ошибки. Дополнительные сведения Не завершает процесс, если в нем есть потоки исполнения, привязанные к прерываниям. |
|
Назначение Завершает процесс. Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Позволяет получить сведения о причине завершения процесса. Параметры
Возвращаемые значения В случае успеха возвращает Дополнительные сведения Через параметры
|
|
Назначение Позволяет получить сведения о необработанном исключении, которое привело к аварийному завершению процесса. Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Позволяет получить контекст потока исполнения, входящего в процесс, который находится в "замороженном" состоянии. Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Позволяет получить сведения о регионе виртуальной памяти, принадлежащем процессу, который находится в "замороженном" состоянии. Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Завершает процесс, который находится в "замороженном" состоянии. Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Позволяет получить код завершения процесса, который завершился по собственной инициативе. Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Позволяет получить идентификатор процесса (PID) для вызывающего процесса. Параметры Нет. Возвращаемые значения Идентификатор процесса. Тип идентификатора определен в заголовочном файле |
|
Назначение Позволяет получить имя вызывающего процесса. Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Позволяет получить имя исполняемого файла (в ROMFS), из которого создан вызывающий процесс. Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Позволяет получить приоритет начального потока процесса. Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Задает приоритет начального потока процесса. Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Регистрирует функцию обработки исключений для вызывающего процесса. Параметры
Возвращаемые значения Идентификатор предыдущей зарегистрированной функции обработки исключений или |
|
Назначение Загружает сегмент ELF-образа в память процесса. Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Резервирует регион виртуальной памяти в процессе. Параметры
Возвращаемые значения В случае успеха возвращает Дополнительные сведения В параметре
Допустимые комбинации флагов, задающих права доступа к региону виртуальной памяти:
|
|
Назначение Освобождает регион виртуальной памяти, зарезервированный вызовом функции Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Задает точку входа в программу и смещение загрузки ELF-образа. Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Загружает таблицу символов Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Задает класс планирования и приоритет начального потока процесса. Параметры
Возвращаемые значения В случае успеха возвращает Дополнительные сведения В параметре В параметре |
|
Назначение Задает начальное значение генератора случайных чисел для поддержки ASLR в заданном процессе. Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Позволяет получить адреса и размеры таблицы символов Параметры
Возвращаемые значения В случае успеха возвращает Дополнительные сведения Если таблица символов Функция предназначена для механизма, который выводит данные обратной трассировки стека и работает в процессе, а не в ядре. В настоящее время этот механизм находится в разработке. |
|
Назначение Позволяет получить идентификатор процесса (PID). Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Инициирует возникновение исключения, которое не может быть обработано и приводит к завершению вызывающего процесса. Параметры Нет. Возвращаемые значения Нет. |
|
Назначение Передает дескриптор процессу, который еще не запущен. Параметры
Возвращаемые значения В случае успеха возвращает Дополнительные сведения В отличие от функции |