Многозадачность и мультипроцессорная обработка

Процессор может выполнять не более одного потока одновременно. Однако многозадачная (multitasking) ОС дает пользователям возможность исполнять несколько программ, причем создается впечатление, будто все они исполняются одновременно. Это достигается следующим образом:

1. Поток исполняется до тех пор, пока его исполнение не будет прервано или пока ему не придется ждать освобождения некоторого ресурса.

2. Сохраняется контекст потока.

3. Загружается контекст другого потока.

4. Этот цикл повторяется до тех пор, пока есть потоки, ожидающие выполнения.

Переключение процессора с исполнения одного потока на исполнение другого называется переключением контекста (context switching). В Windows NT его осуществляет ядро исполнительной системы.

Как показано на примере двух потоков на рис. 4-4, ОС поочередно выполняет то один поток, то другой. В конце концов, каждый поток заканчивает выполнение своей подзадачи и либо завершается, либо получает другую задачу. Очень высокая скорость работы процессора обеспечивает иллюзию одновременного выполнения всех потоков.

Многозадачность увеличивает объем работы, выполняемый системой, потому что большинство потоков не могут исполняться непрерывно. Периодически поток прекращает выполнение и ждет, например, пока медленное устройство ввода-вывода завершит пересылку данных или пока другой поток использует ресурс, необходимый первому. Благодаря многозадачности, пока один поток ожидает, может выполняться другой поток, и время процессора не расходуется впустую.

Многозадачность и мультипроцессорная обработка

Рис. 4-4. Многозадачность,

Вытесняющая многозадачность (preemptive multitasking) — это разновидность многозадачности, при которой ОС не ждет, пока поток добровольно предоставит процессор другим потокам. Вместо этого ОС прерывает поток, после того как он выполнялся в течение заранее заданного периода времени, так называемого кванта времени (time quantum), или когда готов к выполнению поток с большим приоритетом (например, реагирующий на пользовательский ввод). Вытеснение предотвращает монополизацию процессора одним потоком и предоставляет другим потокам их законную долю процессорного времени. Исполнительная система NT — это система с вытесняющей многозадачностью, как и ее основная среда Windows, подсистема Win32. В невытесняющих версиях Windows для MS-DOS, чтобы достичь многозадачности, поток должен был добровольно передавать управление процессором. Плохие или примитивные программы могли захватить процессор в ущерб другим приложениям или всей системе.

Иногда двум потокам необходимо взаимодействовать друг с другом, чтобы скоординировать свои действия для достижения общей цели. Например, в компиляторе С один поток может выполнять препроцессорную обработку программы на С, а другой — принимать результаты работы первого и компилировать их в объектный код. Этим двум потокам необходим способ обмена данными друг с другом.

До второй половины 80-х годов в большинстве ОС программы могли иметь только один поток управления. (Фактически в большинстве ОС для обозначения исполняемой сущности использовалось слово процесс (process). Поток (thread) — достаточно новый термин.) Так как у каждого процесса было отдельное адресное пространство, двум процессам для обмена данными друг с другом нужны были либо область совместно используемой памяти, либо совместно используемый файл. Для такого рода коммуникаций между процессами широко использовались (и используются) каналы (см. рис. 4-5).

Многозадачность и мультипроцессорная обработка

Рис. 4-5, Компилятор, состоящий из двух процессов.

Препроцессорная обработка и компиляция программы двумя процессами (каждый с одним потоком), очевидно, должна идти быстрее, чем в случае одного процесса, так как многозадачная ОС может попеременно исполнять то поток препроцессора, то поток компилятора. Как только препроцессор поместит что-нибудь в совместно используемый буфер, компилятор может начать свою работу. Приложения, подобные этому, которые исполняются в двух или более местах одновременно, называются параллельными приложениями (concurrent applications).

Параллельность полезна приложениям и на однопроцессорном компьютере, но еще более она важна на многопроцессорном. При наличии нескольких процессоров препроцессор и компилятор из нашего примера могут исполняться параллельно. Если параллельное приложение хорошо спроектировано и минимизирует конкуренцию за ресурсы между своими потоками, то на многопроцессорном компьютере оно может работать быстрее, чем на однопроцессорном (сравните рис. 4-6 с рис. 4-4).

Операционной системой с мультипроцессорной обработкой (multiprocessing) называется такая ОС, которая специально спроектирована для работы на компьютерах с более чем одним процессором. ОС с симметричной мультипроцессорной обработкой (symmetric multiprocessing, SMP), такая как Windows NT, может выполнять на любом процессоре как код пользователя, так и код ОС. Если число потоков превышает число процессоров, ОС SMP также поддерживает многозадачность, разделяя время каждого процессора между всеми ожидающими потоками. (Дальнейшие сведения о планировании потоков в Windows NT см. в гл. 7, Ядро).

Многозадачность и мультипроцессорная обработка

Рис. 4-6. Мультипроцессорная обработка.

Многопоточность

Использование двух процессов для достижения параллельности не всегда эффективно. В некоторых системах UNIX, например, когда один процесс создает другой, система должна скопировать все содержимое адресного пространства первого процесса в адресное пространство второго. Для большого адресного пространства эта операция занимает много времени. Более того, два процесса должны установить канал обмена данными друг с другом. Не во всех ОС это осуществляется быстро и легко. Windows NT решает проблему, создавая удобные механизмы совместного использования памяти. Это память копирование при модификации, позволяющая избежать копирования всего адресного пространства из одного процесса в другой, а также оптимизированное для локального использования средство передачи сообщений. (Первая возможность описана в гл. 6, Диспетчер виртуальной памяти, а вторая — механизм локального вызова процедур (LPC) — в гл. 5, Windows и защищенные подсистемы).

Даже при наличии этих усовершенствований бывают ситуации, когда более выгоден другой подход к достижению параллельности, а именно, многопоточный процесс (multithreaded process). Как говорилось ранее, термину поток (thread) отвечает перемещение процессора по командам программы; каждый поток отображает отдельный счетчик команд. У многопоточного процесса имеется два или более потоков (и счетчиков команд), которые совместно используют одно и то же адресное пространство, описатели объектов и другие ресурсы.

Каждый процесс NT создается с одним потоком. При необходимости программа может создать внутри процесса дополнительные потоки. Они часто используются для выполнения в программе асинхронных операций (asynchronous operations), т. е. операций, которые могут иметь место в любое время, безотносительно к основному течению программы. К этой категории часто относятся операции ввода-вывода. Например, можно использовать поток для периодического сохранения редактируемого документа или для опроса устройства пользовательского ввода, например мыши или клавиатуры. Используя один поток для выполнения основной программы и создав второй для опроса устройства ввода, система может по отдельности выполнять обе операции на одном процессоре, так что будет иметь место многозадачность. На многопроцессорном компьютере эти два потока могут выполняться одновременно, притом не требуя расходов на создание второго процесса и инициализацию его адресного пространства.

Чтобы достичь параллелизма с использованием потоков, программа создает два или несколько потоков в одном процессе. Многопоточный компилятор изображен на рис. 4-7.

Многопоточные процессы добиваются параллельности и при этом не имеют недостатков, связанных с использованием двух процессов. Потоки требуют меньших издержек и создаются быстрее, чем процессы (в связи с этим их иногда называют легковесными процессами). Кроме того, поскольку все потоки процесса используют одну и ту же память, за исключением своих стеков и содержимого регистров, не требуется никакого особого механизма обмена данными. Один поток просто записывает свои результаты в память, а другой считывает их. Аналогично, все ресурсы процесса (объекты) одинаково доступны всем его потокам.

Многозадачность и мультипроцессорная обработка

Рис. 4-7. Многопоточный компилятор,

Для выбора порядка, в котором исполняются потоки, ядро NT использует схему, основанную на приоритетах. Потоки с большим приоритетом исполняются прежде потоков с меньшим приоритетом, и ядро периодически изменяет приоритет каждого потока, чтобы гарантировать выполнениеих всех. Приложение может позволить своим потокам выполняться на любом процессоре в многопроцессорной машине или может ограничить их выполнение подмножеством процессоров,

Использование многопоточного процесса — идеальное решение для серверного приложения (например защищенных подсистем Windows NT), которое принимает запросы от клиентов и выполняет по каждому запросу один и тот же код. Например, файл-сервер выполняет операции с файлами; он открывает файлы, читает из них, пишет в них и закрывает их. Хотя каждый запрос может требовать от сервера работы со своим файлом, программа сервера загружается в память только один раз. Каждый приходящий запрос принимается и обрабатывается отдельным потоком сервера, который выполняет необходимую функцию. Все запросы клиентов обслуживаются параллельно. Иллюстрацией этого служит рис. 4-8.

На рисунке два клиентских процесса (каждый с одним потоком, изображенным извилистой линией) используют средство передачи сообщения для посылки сообщения серверному процессу. Имеется несколько серверных потоков для исполнения кода сервера и посылки ответа клиентам.

Обратите внимание, что написание многопоточного приложения требует особой тщательности, так как все потоки процесса имеют полный доступ к его адресному пространству. Потоки могут случайно пересечься друг с другом, выполняя чтение или запись в память не в том порядке.

Такого не происходит, если приложения используют для достижения параллельности два процесса и взаимодействуют явным образом путем посылки сообщений или через каналы. Один процесс не может случайно или намеренно повредить адресное пространство другого. Именно по этой причине защищенные подсистемы Windows NT реализованы как отдельные серверные процессы (и именно поэтому они называются защищенными подсистемами).

Многозадачность и мультипроцессорная обработка

Рис. 4-8, Многопоточный сервер,

Каждая подсистема сохраняет контроль за своим адресным пространством, не допуская вмешательства других подсистем или пользовательских процессов. Внутри сервера, однако, выгодно применять большое число потоков, совместно использующих одно адресное пространство и ресурсы.

Полезны бывают обе техники достижения параллельности, как с использованием нескольких процессов, так и с использованием нескольких потоков. Задачи приложения определяют структуру, наиболее выгодную в данном конкретном случае.

Суммируя сказанное, приведем термины, относящиеся к реализации процессов ОС:

• Многозадачность. Совместное использование процессора потоками, ожидающими выполнения, и создание иллюзии одновременного выполнения всех потоков.

• Мультипроцессорная обработка. Исполнение одного и того же кода ОС как на однопроцессорных, так и на многопроцессорных компьютерах. ОС с симметричной мультипроцессорной обработкой выполняет системный код и код пользователя на всех доступных процессорах.

• Многопоточность. Поддержка нескольких потоков внутри одного процесса.

ОС высокого уровня должна поддерживать все перечисленные возможности. И Windows NT это делает.

Начиная с Windows NT версии 3.51, Service Pack 3 в систему была добавлена новая сущность — волокна (fibers). Волокном называется легкий поток, планировку которого осуществляет приложение. С точки зрения перевода слово волокно надо рассматривать как некий канал (сравни: оптоволокно), который можно использовать для направления потока. В английском языке появление термина fiber более понятно, так как thread дословно переводится как нить. Нить, как известно, состоит из волокон.

Волокна исполняются в контексте тех потоков, которые занимаются их планированием. Каждый поток может управлять несколькими волокнами. В общем случае волокна не дают никаких преимуществ в хорошо спроектированных многопоточных приложениях. Однако использование волокон может оказаться полезным при переносе приложений, разработанных в расчете на планирование своих собственных потоков. Это могут быть приложения, написанные для других платформ.

С точки зрения системы волокна подразумевают индивидуальность потоков, их породивших. Например, если волокно осуществляет доступ к локальной памяти потока, то это будет локальная память именно того потока, который породил волокно. Если волокно вызывает функцию ExitThread, то закроется поток, породивший это волокно.

С волокнами связан гораздо меньший объем информации о состоянии, чем с потоками. У волокон поддерживается только их стек, подмножество регистров и данные, переданные при создании волокна.

Один поток может породить несколько волокон. Однако следует помнить, что одновременно в потоке может исполняться только одно волокно, которое использует все ресурсы, выделенные потоку. Волокно исполняется до тех пор, пока не произойдет переключение на другое волокно внутри потока или пока планировщик не завершит исполнение потока, породившего волокно.

Многозадачность. Когда она полезна, а когда (и как) её стоит избегать?


Похожие статьи.

Понравилась статья? Поделиться с друзьями: