
- •1.1 Основы программирования в операционной системе Windows
- •1.1.1 Вызов функций api
- •1.1.2 Структура программы
- •1.2 Вопросы системного программирования в Windows
- •1.2.1 Страничная и сегментная адресация.
- •1.2.2 Адресное пространство процесса.
- •2.1 Управление процессами
- •2.2 Процессы и потоки в Windows
- •2.3 Создание процессов
- •2.4 Определение исполняемого образа и командной строки
- •2.5 Идентификация процессов
- •3.1 Создание потока. Функция CreateThread
- •3.2. Завершение потока
- •3.3 Другие функции работы с потоками
- •3.4 Структура context
- •3.5 Приоритеты потоков
- •4.1 Объект critical_section
- •4.2 Мьютексы
- •4.3 Семафоры
- •5.1 События
- •7.1 Кучи
- •7.2 Управление памятью кучи
- •Другие функции для работы с кучей
- •Резюме по управлению кучей
- •Отображение адресного пространства процесса в объекты отображения
- •Что такое импорт
- •Явная загрузка dll
- •Явное подключение экспортируемого идентификатора
- •10.1 Управление файлами и каталогами Создание и открытие файлов
- •10.2 Управление каталогами
- •10.3 Другие методы получения атрибутов файлов и каталогов
- •11.1 Блокировка файлов
- •11.2 Реестр
- •12.1 Стандартные устройства и консольный ввод-вывод
- •12.2 Асинхронный ввод-вывод и порты завершения
- •Параметры
- •Цели системы безопасности
- •Параметры
- •Аварийное завершение
- •Использование именованных каналов
- •Параметры
- •Наблюдение за сообщениями в именованном канале
- •Параметры
3.1 Создание потока. Функция CreateThread
HANDLE CreateThread ( PSECURITY_ATTRIBUTES psa;
DWORD cbStack; PTHREAD_START_ROUTINE pfnStartAddr;
PVOID pvParam; DWORD fdwCreate; PDWORD pdwThreadID);
При каждом вызове этой функции система создает объект ядра «поток». Это не сам поток, а компактная структура данных, которая используется операционной системой для управления потоком и хранит статистическую информацию о потоке. Система выделяет память под стек потока из адресного пространства процесса. Новый поток выполняется в контексте того же процесса, что и родительский поток. Поэтому он получает доступ ко всем описателям объектов ядра, всей памяти и стекам всех потоков в процессе. За счет этого потоки в рамках одного процесса могут легко взаимодействовать друг с другом.
Параметры
psa - является указателем на структуру SECURITY_ATTRIBUTES.
cbStack - этот параметр определяет, какую часть адресного пространства поток сможет использовать под свой стек.
pfnStartAddr и pvParam - параметр pfnStartAddr определяет адрес функции потока, с которой должен будет начать работу создаваемый поток, а параметр pvParam идентичен параметру pvParam функции потока.
fdwCreate - этот параметр определяет дополнительные флаги, управляющие созданием потока (0 – исполнение потока начинается немедленно; CREATE_SUSPENDED – система создает поток, инициализирует его и приостанавливает до последующих указаний).
pdwThreadID - это адрес переменной типа DWORD, в которой функция возвращает идентификатор, приписанный системой новому потоку
3.2. Завершение потока
Поток можно завершить четырьмя способами:
- функция потока возвращает управление (рекомендуемый способ);
- поток самоуничтожается вызовом функции ExitThread (нежелательный способ);
- один из потоков данного или стороннего процесса вызывает функцию TerminateThread (нежелательный способ);
- завершается процесс, содержащий данный поток (тоже нежелательно).
Функцию потока следует проектировать так, чтобы поток завершался только после того, как она возвращает управление.
Поток можно завершить принудительно, вызвав:
VOID ExitThread ( DWORD dwExitCode );
При этом освобождаются все ресурсы операционной системы, выделенные данному потоку. В параметр dwExitCode Вы помещаете значение, которое система рассматривает как код завершения потока.
Вызов следующей функции также завершает поток:
BOOL TeminateThread ( HANDLE hThread, DWORD dwExitCode );
В отличие от ExitThread, которая уничтожает только вызывающий поток, эта функция завершает поток, указанный в параметре hThread. После того как поток будет уничтожен, счетчик пользователей его объекта ядра «поток» уменьшится на 1.
3.3 Другие функции работы с потоками
Потоки часто обращаются к API-функциям, которые меняют среду выполнения. Например, потоку может понадобиться изменить свой приоритет или приоритет процесса. В Windows предусмотрены функции, позволяющие легко ссылаться на объекты ядра текущего процесса и потока: HANDLE GetCurrentProcess(), HANDLE GetCurrentThread().
Поток может запросить все временные показатели своего процесса, вызвав GetProcessTimes:
GetProcessTimes(GetCurrentProcess(), &ftCreationTime, &ftExitTime,
&ftKernelTime, &ftUserTime);
Аналогичным образом поток может выяснить собственные временные показатели, вызвав GetThreadTimes:
GetThreadTimes(GetCurrentThread(),&ftCreationTime, &ftExitTime,
&ftKernelTime, &ftUserTime);
Функции, с помощью которых поток может выяснить такой идентификатор - собственный или своего процесса:
DWORD GetCurrentProcessId, DWORD GetCurrentThreadId.
Приостановка и возобновление потоков
В объекте ядра «поток» имеется переменная счетчик числа простоев данного потока. При вызове CreateProcess или CreateThread он инициализируется значением, равным 1, которое запрещает системе выделять новому потоку процессорное время.
После того как поток полностью инициализирован, CreateProcess или CreateThread проверяет, не передан ли ей флаг CREATE_SUSPENDED, и, если да, возвращает управление, оставив поток в приостановленном состоянии.
HANDLE OpenThread ( DWORD dwDesiredAccess, BOOL bInheritHandle,
DWORD dwThreadID).
Функция находит объект ядра «поток» по идентификатору, указанному в dwThreadID, увеличивает его счетчик пользователей на 1 и возвращает описатель объекта. Получив описатель, можно передать его в SuspendThread (или ResumeThread).
Функция Sleep. Поток может сообщить системе не выделять ему процессорное время на определенный период, вызвав:
void Sleep(DWORD dwMilliseconds).
Эта функция приостанавливает поток на dwMilliseconds миллисекунд. Вызывая Sleep, поток добровольно отказывается от остатка выделенного ему кванта времени.
Система прекращает выделять потоку процессорное время на период, примерно равный заданному
Переключение потоков
Функция SwitchToThread позволяет подключить к процессору другой поток (если он есть): BOOL SwitchToThread().
Система проверяет, есть ли поток, которому не хватает процессорного времени. Если нет, SwitchToThread немедленно возвращает управление, а если да, планировщик отдает ему дополнительный квант времени (приоритет этого потока может быть ниже, чем у вызывающего). По истечении этого кванта планировщик возвращается в обычный режим работы.
SwitchToThread позволяет потоку, которому не хватает процессорного времени, отнять этот ресурс у потока с более низким приоритетом. Она возвращает FALSE, если на момент ее вызова в системе нет ни одного потока, готового к исполнению; в ином случае — ненулевое значение.
Определение периодов выполнения потока
BOOL GetThreadTimes(HANDLE hThread, PFILETIME pftCreationTime,
PFILETIME pftExitTime, PFILETIME pftKernelTime,
PFILETME pftUserTime)