Управление потоками исполнения (низкоуровневый API thread_api.h)
API определен в заголовочном файле sysroot-*-kos/include/coresrv/thread/thread_api.h
из состава KasperskyOS SDK.
Основные возможности API:
- создавать, завершать, блокировать потоки исполнения;
- возобновлять исполнение заблокированных потоков;
- изменять приоритеты и классы планирования потоков исполнения;
- обрабатывать исключения;
- отвязывать потоки исполнения от прерываний;
- выполнять привязку потоков исполнения к процессорам (вычислительным ядрам).
Функции API, которые принимают на вход или возвращают идентификатор потока исполнения (TID), являются устаревшими и в будущем будут удалены. Эти функции не описаны в этом разделе.
Сведения о функциях API приведены в таблице ниже.
Библиотека libkos
также предоставляет высокоуровневый API для управления потоками исполнения, который определен в заголовочном файле sysroot-*-kos/include/kos/thread.h
из состава KasperskyOS SDK. Рекомендуется использовать именно этот API. Низкоуровневый API следует использовать, если недостаточно возможностей высокоуровневого API.
Создание потоков исполнения. Классы планирования потоков исполнения
Чтобы создать поток исполнения, нужно вызвать функцию KnThreadCreateByHandle()
. Через параметр flags
этой функции для создаваемого потока исполнения можно задать следующие классы планирования:
- класс планирования стандартных потоков;
- класс планирования потоков реального времени FIFO (англ. First In, First Out);
- класс планирования потоков реального времени RR (англ. Round-Robin).
Приоритет стандартного потока исполнения может принимать значения от 0 до 15. Чем выше приоритет стандартного потока исполнения, тем больше размер квантов времени, выделяемых этому потоку, и тем чаще эти кванты выделяются. Один стандартный поток исполнения с высоким приоритетом может занимать несколько мест подряд в очереди потоков исполнения. Стандартные потоки исполнения не могут вытеснять другие стандартные потоки исполнения, а также потоки исполнения реального времени независимо от соотношения приоритетов. Если в очереди появляется поток исполнения реального времени, то текущий стандартный поток исполнения немедленно передает ему управление. Если в очереди нет потоков исполнения реального времени, то текущий стандартный поток исполнения передает управление следующему, если завершился, стал заблокированным, исчерпал свой квант времени или отдал его следующему.
Приоритет потока исполнения реального времени может принимать значения от 0 от 31. Более приоритетные потоки исполнения реального времени вытесняют менее приоритетные. Также потоки исполнения реального времени вытесняют стандартные потоки исполнения независимо от соотношения приоритетов. Передача управления от текущего потока исполнения реального времени следующему в очереди осуществляется в следующих случаях:
- Текущий поток исполнения реального времени с классом планирования FIFO завершился или стал заблокированным, либо в очереди появился поток исполнения реального времени с более высоким приоритетом.
Пока поток исполнения реального времени с классом планирования FIFO не будет завершен, заблокирован или вытеснен потоком исполнения реального времени с более высоким приоритетом, он может сколь угодно долго не передавать управление следующему.
- Текущий поток исполнения реального времени с классом планирования RR завершился, стал заблокированным или исчерпал свой квант времени, либо в очереди появился поток исполнения реального времени с более высоким приоритетом.
Поток исполнения реального времени с классом планирования RR, который не был завершен, заблокирован или вытеснен потоком исполнения реального времени с более высоким приоритетом, передает управление следующему по истечении своего кванта времени, если следующий является потоком исполнения реального времени с таким же приоритетом. В противном случае осуществляется передача управления снова себе.
- Текущий поток исполнения реального времени отдал свой квант времени следующему в очереди потоку исполнения реального времени с таким же приоритетом.
Поток исполнения реального времени может отдать свой квант времени следующему, если следующий является потоком исполнения реального времени с таким же приоритетом. В противном случае осуществляется передача управления снова себе.
Исполнение потоков реального времени с более низким приоритетом начинается только после того, как каждый из потоков реального времени с более высоким приоритетом завершился или стал заблокированным. Потоки исполнения реального времени с одним приоритетом образуют очередь по принципу FIFO.
Класс планирования потока исполнения можно изменить вызовом функции KnThreadSetSchedPolicyByHandle()
. Также эта функция позволяет изменить размер кванта времени, выделенного потоку исполнения реального времени с классом планирования RR. Это значение является единственным параметром класса планирования потоков реального времени RR, который по умолчанию имеет значение 10 мс, но может принимать значения от 2 мс до 100 мс. Класс планирования стандартных потоков и класс планирования потоков реального времени FIFO не имеют параметров.
Приоритет потока исполнения можно изменить вызовом функции KnThreadSetSchedPolicyByHandle()
или KnThreadSetPriorityByHandle()
.
После привязки к прерыванию поток исполнения становится потоком исполнения реального времени с классом планирования FIFO и приоритетом выше 31 независимо от того, какой класс планирования и приоритет были у этого потока исполнения до привязки к прерыванию. (О привязке потока исполнения к прерыванию см. "Управление обработкой прерываний (irq.h)".)
Для потоков исполнения, привязанных к прерываниям, нельзя применять многие функции API, в том числе KnThreadCreateByHandle()
, KnThreadSetPriorityByHandle()
, KnThreadSuspendCurrent()
, KnThreadResumeByHandle()
, KnThreadTerminateByHandle()
, KnThreadWaitByHandle()
, KnSleep()
, KnThreadSetSchedPolicyByHandle()
.
Создание дескрипторов потоков исполнения
Дескриптор потока исполнения создается при создании потока исполнения вызовом функции KnThreadCreateByHandle()
. Также поток исполнения (в том числе начальный) может создать свой дескриптор вызовом функции KnThreadOpenCurrent()
.
Дескриптор потока исполнения нельзя передать другому процессу через IPC.
Обработка исключений
Чтобы зарегистрировать функцию обработки исключений для потока исполнения, нужно вызвать функцию KnThreadSetExceptionHandler()
. Эта функция дерегистрирует предыдущую функцию обработки исключений и возвращает ее идентификатор. Сохранив этот идентификатор, в дальнейшем можно снова зарегистрировать предыдущую функцию обработки исключений.
Чтобы получить сведения о последнем исключении потока исполнения, в обработчике исключений нужно вызвать функцию KnThreadGetLastException()
.
Отвязывание потоков исполнения от прерываний
Чтобы отвязать поток исполнения от прерывания, нужно вызвать функцию KnThreadDetachIrq()
. (Подробнее об использовании функции KnThreadDetachIrq()
см. "Управление обработкой прерываний (irq.h)".)
После отвязывания от прерывания поток исполнения получает класс планирования и приоритет, которые были у этого потока исполнения до привязки к прерыванию.
Привязка потоков исполнения к процессорам (вычислительным ядрам)
Чтобы ограничить набор процессоров (вычислительных ядер), которые могут быть использованы для исполнения потока, нужно задать для этого потока маску сходства. Маска сходства (англ. Affinity Mask) – битовая маска, указывающая на каких процессорах (вычислительных ядрах) должен исполняться поток.
Чтобы создавать, корректировать и выполнять другие операции с масками сходства, нужно использовать API, определенный в заголовочном файле sysroot-*-kos/include/rtl/cpuset.h
из состава KasperskyOS SDK.
Чтобы задать маску сходства потока исполнения, нужно вызвать функцию KnThreadSetAffinityByHandle()
.
Завершение потоков исполнения
Завершение потока исполнения представляет собой его перманентное удаление из планировщика. Поток исполнения завершается в следующих случаях:
- Осуществлен выход из функции, выполняемой потоком исполнения.
Должен быть осуществлен выход оператором
return
из корневой (не из вложенной) функции, выполняемой потоком исполнения. - Вызвана функция
KnThreadTerminateByHandle()
илиKnThreadExit()
.Функция
KnThreadExit()
завершает поток исполнения, даже если вызвана не из корневой функции, выполняемой потоком исполнения, а из вложенной. - Завершился или перешел в "замороженное" состояние процесс.
О "замороженном" состоянии процесса см. "Управление процессами (низкоуровневый API task_api.h)".
Коды завершения потоков исполнения определяются разработчиком решения на базе KasperskyOS . Эти коды нужно указывать в параметре code
функций KnThreadTerminateByHandle()
и KnThreadExit()
, а также при вызове оператора return
в функции, выполняемой потоком исполнения. Чтобы получить код завершения потока исполнения, нужно вызвать функцию KnThreadWaitByHandle()
.
Получение адреса TCB и задание базового адреса TLS потоков исполнения
Блок управления потоком исполнения (англ. Thread Control Block, TCB) – структура, содержащая сведения о потоке исполнения, которые используются ядром для управления этим потоком исполнения. Тип структуры определен в заголовочном файле sysroot-*-kos/include/thread/tcbpage.h
из состава KasperskyOS SDK. TCB содержит базовый адрес локальной памяти потока исполнения (TLS). Получить адрес TCB позволяет функция KnThreadGetTcb()
. Задать базовый адрес TLS позволяет функция KnThreadSetTls()
. Эти функции предназначены для использования библиотекой libc
.
Получение сведений о потоке исполнения
Получить базовый адрес и размер стека потока исполнения, а также идентификатор потока исполнения (TID) позволяет функция KnThreadGetInfoByHandle()
. Эта функция предназначена для использования библиотекой libc
.
Освобождение ресурсов завершившихся потоков исполнения
Ресурсами потока исполнения являются его стек, контекст и TCB. Чтобы ресурсы потока исполнения были освобождены после его завершения, нужно до или после завершения этого потока исполнения закрыть его дескриптор вызовом функции KnHandleClose()
, которая объявлена в заголовочном файле sysroot-*-kos/include/coresrv/handle/handle_api.h
из состава KasperskyOS SDK. (Исключением является начальный поток процесса, ресурсы которого освобождаются без вызова функции KnHandleClose()
, если начальный поток не создавал свой дескриптор вызовом функции KnThreadOpenCurrent()
.) Также ресурсы потоков исполнения освобождаются при завершении процесса, в который они входят.
Сведения о функциях API
Функции thread_api.h
Функция |
Сведения о функции |
---|---|
|
Назначение Создает поток исполнения. Параметры
Возвращаемые значения В случае успеха возвращает Дополнительные сведения В параметре
По умолчанию создается стандартный поток исполнения. Дескрипторы потоков исполнения нельзя передавать между процессами через IPC. |
|
Назначение Создает дескриптор вызывающего потока исполнения. Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Позволяет получить приоритет потока исполнения. Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Задает приоритет потока исполнения. Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Блокирует вызывающий поток исполнения. Параметры Нет. Возвращаемые значения В случае успеха возвращает |
|
Назначение Возобновляет исполнение заблокированного потока. Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Завершает поток исполнения. Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Завершает вызывающий поток исполнения. Параметры
Возвращаемые значения Код ошибки. |
|
Назначение Позволяет получить сведения о потоке исполнения. Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Блокирует вызывающий поток исполнения до завершения заданного потока исполнения. Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Блокирует вызывающий поток исполнения на заданное время. Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Позволяет получить адрес блока управления потоком исполнения (TCB) для вызывающего потока исполнения. Параметры Нет. Возвращаемые значения Указатель на TCB. Тип данных для хранения TCB определен в заголовочном файле |
|
Назначение Задает базовый адрес локальной памяти потока исполнения (TLS) для вызывающего потока исполнения. Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Отвязывает вызывающий поток исполнения от прерывания, обрабатываемого в его контексте. Параметры Нет. Возвращаемые значения В случае успеха возвращает |
|
Назначение Регистрирует функцию обработки исключений для вызывающего потока исполнения. Параметры
Возвращаемые значения Идентификатор предыдущей зарегистрированной функции обработки исключений или |
|
Назначение Позволяет получить сведения о последнем исключении вызывающего потока исполнения. Параметры
Возвращаемые значения Нет. |
|
Назначение Позволяет получить маску сходства потока исполнения. Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Задает маску сходства потока исполнения. Параметры
Возвращаемые значения В случае успеха возвращает |
|
Назначение Позволяет получить сведения о классе планирования потока исполнения. Параметры
Возвращаемые значения В случае успеха возвращает Дополнительные сведения В параметре В параметре |
|
Назначение Задает класс планирования и приоритет потока исполнения. Параметры
Возвращаемые значения В случае успеха возвращает Дополнительные сведения В параметре В параметре |