Организация мультизадачности для приложений WIN32
С приложением в WIN32 связаны два основных понятия: процесс (process) и поток (thread). В терминах WIN32 под процессом понимается экземпляр выполняемой программы. Процесс является владельцем всех ресурсов, выделяемых операционной системой приложению для его выполнения. Процессы WIN32 инертны, то есть они не выполняются, а лишь владеют ресурсами. Последовательность выполнения команд в рамках процесса задается потоком, который рассматривается как ресурс, создаваемый процессом. В отличие от предыдущих версий Windows, в WIN32 прикладной программист имеет возможность в рамках одного процесса создать несколько параллельных потоков и обеспечить их взаимодействие и синхронизацию. Мультизадачность в Windows95 и Windows NT 4.0 основана на разделении процессорного времени между отдельными потоками, а не процессами. При этом WindowsNT 4.0 поддерживает симметричную мультипроцессорную архитектуру, что позволяет не только разделять время между потоками на одном процессоре, как это имеет место в Windows 95, но и запускать параллельные потоки одновременно на разных процессорах. Разделение времени между потоками и распределение потоков по процессорам выполняется ядром ОС прозрачно для программиста. С точки зрения последнего, имеется набор функций API, позволяющих создавать и синхронизировать параллельные потоки, причем принцип программирования с использованием этих функций не зависит от того, имеется ли в системе один или несколько процессоров. Таким образом, API WIN32 предоставляет достаточно широкий набор средств параллельного программирования.
ОС создает и манипулирует несколькими различными типами управляющих структур данных, называемых объектами ядра (kernelobjects). К объектам ядра относятся процессы (process objects), потоки (thread objects), файлы (file objects), семафоры (semaphore objects), события (event objects), объекты взаимоисключения (mutex objects), каналы (pipe objects), почтовые ящики (mailslotobjects) и некоторые другие. Назначение некоторых из перечисленных типов объектов ядра мы рассмотрим немного позже в этой главе. Для создания объекта каждого типа используются соответствующие функции API. Когда объект ядра больше не требуется, его обязательно следует закрыть при помощи универсальной функции CloseHandle. Каждый объект ядра может находиться в одном из двух состояний: свободном (signaled) и занятом (nonsignaled). При помощи специальных функций API поток может быть переведен в состояние ожидания до тех пор, пока не освободится (перейдет в состояние signaled) некоторый объект ядра, что широко используется для синхронизации параллельных потоков. Кроме того, каждый объект ядра имеет счетчик числа пользователей. При создании объекта ядра значение счетчика равно 1. Если при помощи соответствующей функции API поток получает идентификатор объекта ядра типа HANDLE, значение счетчика увеличивается на 1. Функция CloseHandle уменьшает значение счетчика, но объект ядра удаляется ею из системы только если значение счетчика равно нулю (закрыт последний идентификатор объекта ядра (handle), связанный с объектом).
предыдущая темаследующая