Аннотация: Основные термины и понятия, необходимые для обсуждения параллельных вычислений; общие подходы к созданию многопроцессорных вычислительных установок и планирование потоков в операционных системах.
Многозадачность в Windows
Для современных операционных систем и для различных систем программирования в современном мире поддержка разработки и реализация многозадачности стала необходимой. При этом на применяемые решения влияет значительное число факторов.
Конкретная реализация очень сильно зависит от того, какая вычислительная система и какие аспекты работы этой системы рассматриваются с точки зрения многозадачности. Так, например, в некоторых случаях эффективным способом реализации многозадачности может быть использование асинхронных операций ввода-вывода; в других случаях будет целесообразным использование механизмов передачи сообщений; очень часто применяется обмен данными через область совместно доступной памяти. Поэтому знакомство следует начать с основных сведений о вычислительных системах.
Современные операционные системы, как правило, поддерживают несколько различных механизмов многозадачности. Конкретный выбор в конкретной системе зачастую оказывает значительное влияние на правила разработки приложений. Поэтому следующим шагом должно быть знакомство с поддержкой многозадачности операционными системами. Мы рассмотрим в общих чертах реализацию многозадачности в Windows.
Однако, главным является не компьютер и не установленная на нем операционная система — всё это делается только для того, чтобы обеспечить эффективное выполнение приложений. Соответственно знакомство с многозадачностью должно завершиться обсуждением средств, которые операционная система предоставляет разработчикам приложений, и некоторым приемам разработки приложений.
Основные понятия
Начиная знакомство с многозадачными системами, необходимо выделить понятия мультипроцессирования и мультипрограммирования.
- Мультипроцессирование — использование нескольких процессоров для одновременного выполнения задач.
- Мультипрограммирование — одновременное выполнение нескольких задач на одном или нескольких процессорах.
В завершение знакомства укажем некоторые термины, определяющие базовые понятия, которыми оперируют операционные системы.
Мультипроцессирование
Говоря о мультипроцессировании, необходимо выделить ситуации, когда используются различные виды оборудования, например, одновременная работа центрального процессора и графического ускорителя видеокарты; либо когда организуется одновременная работа равноправных устройств, выполняющих сходные задачи. Последний случай (см. рис. 6.1) также предполагает различные подходы — с выделением управляющего и подчиненных устройств (асимметричное мультипроцессирование), либо с использованием полностью равноправных (симметричное мультипроцессирование).
Рис.
6.1.
Разные подходы к реализации мультипроцессирования
В современных компьютерах одновременно сосуществует несколько различных реализаций мультипроцессирования. Так, например, практически всегда применяются функционально различные устройства — центральный процессор, видеосистема, контроллеры прямого доступа к памяти (по сути, специализированные процессоры), интеллектуальные периферийные устройства и так далее. В большинстве случаев организация одновременной работы функционально различных устройств осуществляется на уровне операционной системы и требует непосредственного доступа к аппаратуре компьютера. Для разработчиков приложений возможность использования такого мультипроцессирования во многих случаях ограничивается применением асинхронных функций ввода-вывода.
Кроме того, очень часто используются многопроцессорные вычислительные системы, в которых используется несколько центральных процессоров. Сложилось несколько подходов к созданию таких компьютеров:
- наиболее массовыми являются так называемые SMP (Shared Memory Processor или Symmetric MultiProcessor) машины. В таких компьютерах несколько процессоров подключены к общей оперативной памяти и имеют к ней равноправный и конкурентный доступ (см. рис. 6.2). По мере увеличения числа процессоров производительность оперативной памяти и коммутаторов, связывающих процессоры с памятью, становится критически важной. Обычно в SMP используются 2-8 процессоров; реже число процессоров достигает десятков. Взаимодействие одновременно выполняющихся процессов осуществляется посредством использования общей памяти, к которой имеют равноправный доступ все процессоры.
Рис.
6.2.
SMP компьютер - при необходимости создания систем с качественно большим числом процессоров прибегают к MPP (Massively Parallel Processors) системам. Для этого используют несколько однопроцессорных или SMP-систем, объединяемых с помощью некоторого коммуникационного оборудования в единую сеть (см. рис. 6.3). При этом может применяться как специализированная высокопроизводительная среда передачи данных, так и обычные сетевые средства — типа Ethernet. В MPP системах оперативная память каждого узла обычно изолирована от других узлов, и для обмена данными требуется специально организованная пересылка данных по сети. Для MPP систем критической становится среда передачи данных; однако в случае мало связанных между собой процессов возможно одновременное использование большого числа процессоров. Число процессоров в MPP системах может измеряться сотнями и тысячами.
Рис.
6.3.
MPP система - иногда используют так называемые NUMA и cc-NUMA архитектуры; они являются компромиссом между SMP и MPP системами: оперативная память является общей и разделяемой между всеми процессорами, но при этом память неоднородна по времени доступа. Каждый процессорный узел имеет некоторый объем оперативной памяти, доступ к которой осуществляется максимально быстро; для доступа к памяти другого узла потребуется значительно больше времени (см. рис. 6.4). cc-NUMA отличается от NUMA тем, что в ней на аппаратном уровне решены вопросы когерентности кэш-памяти (cache-coherent) различных процессоров. Формально на NUMA системах могут работать обычные операционные системы, созданные для SMP систем, хотя для обеспечения высокой производительности приходится решать нетипичные для SMP задачи оптимального размещения данных и планирования с учетом неоднородности памяти.
Рис.
6.4.
NUMA или cc-NUMA система
Таким образом, с точки зрения реализации мультипроцессирования, для разработчиков ПО важно иметь представление о том, каковы средства взаимодействия между параллельно работающими ветвями кода — общая память с равноправным или неравноправным доступом, либо некоторая коммуникационная среда с механизмом пересылки данных. Наибольшее распространение получили SMP и MPP системы, соответственно, большинство операционных систем содержат необходимые средства для эффективного управления SMP системами. Для реализации MPP систем, как правило, используются обычные операционные системы на всех узлах и либо обычные сетевые технологии, с применением распространенных стеков протоколов, либо специфичное коммуникационное оборудование со своими собственными драйверами и собственными средствами взаимодействия с приложениями. NUMA системы распространены в меньшей степени, хотя выпускаются серийно. Нормальным при этом является применение массовых операционных систем, рассчитанных на SMP установки, несмотря на то, что это несколько снижает эффективность использования NUMA.
Windows содержит встроенные механизмы, необходимые для работы на SMP; также возможна установка этой ОС на cc-NUMA системах (современные версии Windows имеют механизмы поддержки cc-NUMA систем). Специальных, встроенных в ОС средств для исполнения приложений на MPP системах в Windows не предусмотрено. Windows предполагает альтернативное применение MPP систем, построенных на обычных сетях, для реализации web- или файловых серверов с балансировкой нагрузки по узлам кластера.
Мультипрограммирование
Мультипрограммирование (то есть одновременное выполнение разного кода на одном или нескольких процессорах) возможно и без реального мультипроцессирования. Конечно, при наличии только одного процессора должен существовать некоторый механизм, обеспечивающий переключение процессора между разными выполняемыми потоками. Такой режим разделения процессорного времени позволяет одному процессору обслуживать несколько задач «как бы одновременно»: осуществляя быстрое переключение между разными задачами и выполняя в данный момент времени код только одной задачи, процессор создает иллюзию одновременного выполнения кода разных задач. Более того, даже на многопроцессорных системах при реальной возможности распараллеливания задач по разным процессорам, обычно используют механизм разделения времени на каждом из доступных процессоров. Формально мультипрограммирование предполагает именно разделение процессорного времени, поэтому иногда его противопоставляют мультипроцессированию: реализация многозадачности на одном процессоре в противовес использованию многих процессоров.
Важно подчеркнуть, что мультипрограммирование предполагает управление одновременно выполняющимися приложениями пользователя, а не вообще всяким кодом. Любая реальная вычислительная система должна предусматривать специальные меры для своевременного обслуживания поступающих прерываний, исключений и остановок. Такое обслуживание должно выполняться независимо от работы приложений пользователя и в большинстве случаев имеет абсолютный приоритет над приложениями, так как задержка в обработке подобных событий чревата возникновением неустранимых сбоев и потерь данных. В результате операционные системы предоставляют некоторый механизм, обслуживающий возникающие прерывания и только в промежутках между прерываниями — приложения пользователя. Более того, поскольку аппаратные прерывания происходят в большинстве случаев асинхронно по отношению к приложениям и по отношению к другим прерываниям, то получается так, что система должна содержать два планировщика или диспетчера — один для прерываний, другой для приложений. Работа диспетчера прерываний здесь не рассматривается, поскольку относится сугубо к ядру операционной системы и практически не затрагивает работу приложений.
В мультипрограммировании ключевым местом является способ составления расписания, по которому осуществляется переключение между задачами (планирование), а также механизм, осуществляющий эти переключения.
По времени планирования можно выделить статическое и динамическое составление расписания (см. рис. 6.5). При статическом планировании расписание составляется заранее, до запуска приложений, и операционная система в дальнейшем просто выполняет составленное расписание. В случае динамического планирования порядок запуска задач и передачи управления задачам определяется непосредственно во время исполнения. Статическое расписание свойственно системам реального времени, когда необходимо гарантировать заданное время и сроки выполнения необходимых операций. В универсальных операционных системах статическое расписание практически не применяется.
Рис.
6.5.
Планирование задач
Динамическое расписание предполагает составление плана выполнения задач непосредственно во время их выполнения. Выделяют динамическое планирование с использованием квантов времени — когда каждой выполняемой задаче назначают определенной продолжительности квант времени (фиксированной или переменной продолжительности) и планирование с использованием приоритетов — когда задачам назначают специфичные приоритеты и переключение задач осуществляют с учетом этих приоритетов. В реальных операционных системах обычно имеет место какая-либо комбинация этих подходов.
Понятия абсолютных и относительных приоритетов связаны с их влиянием на момент переключения с одной задачи на другую: в системах с абсолютными приоритетами такое переключение выполняется, как только в очереди готовых к исполнению задач появляется задача с более высоким приоритетом, чем выполняемая. В системах с относительными приоритетами появление более приоритетной задачи не приводит к немедленному переключению — момент переключения задач будет определяться по каким-либо иным критериям.
Выделяют понятия вытесняющей и невытесняющей многозадачности: в случае невытесняющей многозадачности решение о переключении принимает выполняемая в данный момент задача, а в случае вытесняющей многозадачности такое решение принимается операционной системой (или иным арбитром), независимо от работы активной в данный момент задачи.
На приведенном графе состояний задачи (см. рис. 6.6) прямая линия от состояния «выполнение» к состоянию «готовность» нарисована пунктиром, чтобы выделить отличие невытесняющей многозадачности от вытесняющей. В случае невытесняющей многозадачности выполняющаяся задача может либо завершиться, либо перейти в состояние «ожидание».
Рис.
6.6.
Граф состояния задачи
И тот, и другой переходы определены логикой работы самой задачи. На графе состояний задачи в случае невытесняющей многозадачности пунктирной линии от состояния «выполнение» к состоянию «готовность» не будет. В случае вытесняющей многозадачности вытеснение осуществляется по решению системы, а не только по инициативе задачи.
Для невытесняющей многозадачности характерно, что операционная система передает задаче управление и далее ожидает от нее сигнала, информирующего о возможности переключения на другую задачу; сама по себе операционная система выполняемую задачу не прерывает. Именно поэтому невытесняющая многозадачность рассматривается как многозадачность с относительными приоритетами — пока задача сама не сообщит, что настал подходящий для переключения момент, система не сможет передать управление никакой другой, даже высокоприоритетной, задаче.
Невытесняющая многозадачность проста в реализации, особенно на однопроцессорных машинах, и, кроме того, обеспечивает очень малый уровень накладных расходов на реализацию плана. Недостатками являются повышенная сложность разработки приложений и невысокая защищенность системы от некачественных приложений.
Характерный пример невытесняющей многозадачности — 16-ти разрядные Windows (включая собственно 16-ти разрядные версии Windows, выполнение 16-ти разрядных приложений в Windows-95, 98, ME и выполнение 16-ти разрядных приложений в рамках одной Windows-машины в NT, 2000, XP и 2003). В таких приложениях операционная система не прерывает выполнение текущей задачи до вызова ею функций типа GetMessage или WaitMessage, во время которых Windows осуществляет при необходимости переключение на другую задачу.
Вытесняющая многозадачность предполагает наличие некоторого арбитра, принадлежащего обычно операционной системе, который принимает решение о вытеснении текущей выполняемой задачи какой-либо другой, готовой к выполнению, асинхронно с работой текущей задачи.
В качестве некоторого обобщения можно выделить понятие «момент перепланирования», когда активируется планировщик задач и принимает решение о том, какую именно задачу в следующий момент времени надо начать выполнять. Принципы, по которым назначаются моменты перепланирования, и критерии, по которым осуществляется выбор задачи, определяют способ реализации многозадачности и его сильные и слабые стороны.
Так, если моменты перепланирования наступают только вследствие явного вызова функций приложением, мы имеем дело с невытесняющей многозадачностью и относительными приоритетами. Если смена приоритета вызывает перепланирование — значит, это система с абсолютными приоритетами и вытесняющей многозадачностью. Если моменты перепланирования наступают по исчерпанию временных квантов (возможно постоянного размера, а возможно и переменного), то система поддерживает вытесняющую многозадачность с квантованием.
Большинство современных операционных систем используют комбинированные планировщики, одновременно применяющие квантование с переменной продолжительностью кванта и абсолютные или относительные приоритеты (см. рис. 6.7).
Рис.
6.7.
Моменты перепланирования задач
Выбор задачи, которая начнет выполняться вследствие срабатывания планировщика, также определяется многими факторами. Среди важнейших — приоритет готовых к исполнению задач. Однако, помимо этого, часто принимают во внимание текущее и предыдущее состояния задачи. Такой подход позволяет реализовать достаточно сложный и тщательно сбалансированный планировщик задач. Очень часто применяют такой прием: назначенный задаче приоритет рассматривается в качестве некоторого «базового», а планировщик операционной системы может в определенных рамках корректировать реальный приоритет в зависимости от истории выполнения задачи. Типичными причинами коррекции приоритета являются:
- запуск задачи (для возможно скорейшего начала исполнения);
- досрочное освобождение процессора до исчерпания отведенного кванта (велик шанс, что задача и в этот раз так же быстро отдаст управление);
- частый вызов операций ввода-вывода (при этом задача чаще находится в ожидании завершения операции, нежели занимает процессорное время);
- продолжительное ожидание в очереди (приоритет ожидающей задачи часто постепенно начинают увеличивать);
- и многие другие.
Работа планировщика существенно усложняется в случае SMP машин, когда необходимо принимать во внимание привязку задач к процессорам (иногда задаче можно назначить конкретный процессор) и то, на каком процессоре задача выполнялась до того (это позволяет эффективнее использовать кэш-память процессора).
Реализации Windows NT, 2000, XP, 2003+ предусматривают достаточно развитый и сложный планировщик, учитывающий множество факторов и корректирующий как назначение и длительность отводимых задаче квантов, так и приоритеты задач. При этом планировщик является настраиваемым, и его логика работы несколько отличается в зависимости от настроек системы (некоторые доступны через панель управления) и от назначения системы (работа планировщика различна у серверов и рабочих станций).
Важно отметить, что Windows является гибкой системой разделения времени с вытесняющей многозадачностью и не может рассматриваться в качестве системы реального времени. Даже те процессы, которые с точки зрения Windows относятся к классу процессов так называемого «реального времени», на самом деле требованиям, предъявляемым к системам реального времени, не удовлетворяют. Такие процессы получат приоритетное распределение процессорного времени и будут обрабатываться планировщиком с учетом их «особого статуса»; однако при этом нельзя гарантировать строгого выполнения временных ограничений. Более того, в силу используемых механизмов управления памятью, нельзя точно предсказать время, необходимое для выполнения той или иной операции. В любой момент времени при самом невинном обращении к какой-либо переменной или функции может потребоваться обработка ошибок доступа, подкачка выгруженных страниц, освобождение памяти и т.д. — то есть действия, время завершения которых предсказать крайне трудно. Фактически можно давать лишь вероятностные прогнозы по времени выполнения той или иной операции. До определенных рамок Windows можно применять в мягких системах реального времени — с достаточно свободными ограничениями, но даже незначительная вероятность превышения временных ограничений иногда просто недопустима.
Базовая терминология
В операционных системах сложилось несколько подходов к реализации многозадачности, и, соответственно, принятая в разных операционных системах терминология несколько отличается. Так, обычно разделяют понятия задачи, процесса и потока. При этом понятие задачи является в большей степени историческим, либо очень специфичным. Это понятие сформировалось, когда единицей выделения процессорного времени была сама задача; планировщик же мог только переключать задачи. В современных системах большее распространение получил подход, в котором в рамках одной «задачи» может быть выделено несколько одновременно выполняемых ветвей кода, соответственно термин «задача» заместился терминами «процесс» и «поток».
Процесс является объектом планирования адресного пространства и некоторых ресурсов, выделенных задаче. Но при этом процесс не является потребителем процессорного времени и не подлежит планированию.
Поток является объектом планирования процессорного времени. Дополнительно к этому с потоком ассоциируют некоторые другие свойства, например, пользователя, — это позволяет потокам даже одного процесса действовать от имени разных пользователей (воплощение) и использовать механизмы ограничения доступа к ресурсам операционной системы. Например, сервер, предоставляющий доступ к каким-либо файлам, может создать поток, обслуживающий конкретного клиента, и воплотить его с правами доступа, назначенными этому клиенту. Однако в данный момент для нас важно, что управление процессорным временем осуществляется применительно к потокам, а управление адресным пространством — применительно к процессам; каждый процесс содержит, как минимум, один поток.
Принято также деление потоков на потоки ядра и потоки пользователя (эти термины тоже неоднозначны). Потоки ядра в данном контексте являются потоками, для управления которыми предназначен планировщик, принадлежащий ядру операционной системы. Потоки пользователя при этом рассматриваются как потоки, которые управляются планировщиком пользовательского процесса. Строго говоря, потоки пользователя являлись переходным этапом между «задачами» и «процессами»: с точки зрения операционной системы использовались «задачи», которым выделялись и ресурсы, и процессорное время, тогда как разделение «задачи» на «потоки» осуществлялось непосредственно в самом приложении.
В Windows для обозначения этих понятий использованы термины process (процесс), thread (поток) и fiber (волокно). Достаточно часто термин «thread» переводится на русский язык как «нить», а не «поток». Термин «fiber» также может переводиться либо как «нить», либо как «волокно». Поток соответствует потоку ядра и планируется ядром операционной системы, а волокно соответствует потоку пользователя и планируется в приложении пользователя.
В операционной системе для описания потоков используются объекты двух типов — так называемые дескрипторы и контекст. Дескрипторы содержат информацию, описывающую поток, но не его текущее состояние исполнения. Контекст потока содержит информацию, описывающую непосредственно состояние исполнения потока. Так, например, дескриптор должен содержать переменные окружения, права доступа, назначенные потоку, приоритет, величину кванта и так далее, тогда как контекст должен сохранять информацию о состоянии стека, регистров процессора и т.д. Дескрипторы содержат актуальную в каждый момент информацию, а контекст обновляется в тот момент, когда поток выходит из исполняемого состояния. Из контекста восстанавливается состояние потока при возобновлении исполнения. Пока поток выполняется, содержимое контекста не является актуальным и не соответствует его реальному состоянию.
Марат Хайрулин, эксперт Microsoft в России, продолжает исследовать нюансы работы с несколькими задачами и рассказывает о совмещении окон и разделении экрана, о вашей личной машине времени для сайтов и документов, и о реальной пользе виртуальных столов.
В прошлой заметке мы писали о том, как современная наука относится к многозадачности и делились небольшими приемами, которые помогут сосредоточиться на одной задаче. А теперь хочтим напомнить (а кого-то может быть и познакомить) с полезными возможностями, которые помогут, если решение вашей задачи требует работы сразу с несколькими приложениями.
Переключение по-старому и по-новому
Переключение между приложениями – наверное то, что большинство из нас делает «на автомате», и никого, конечно, не удивит сочетание клавиш Alt + Tab. Но если одновременно нажать также и Ctrl (то есть Ctrl + Alt + Tab), то эта комбинация зафиксирует меню со всеми открытыми окнами на экране и позволит выбрать нужное приложение одним кликом мыши или касанием пальца (выбрать окно можно также с помощью стрелок на клавиатуре, а открыть – с помощью Enter). Может быть полезно, когда у вас открыто много окон.
Чуть менее известное, но тоже классическое сочетание клавиш Windows + Tab дает больше возможностей, чем кажется на первый взгляд.
Нажимая эти клавиши в актуальных версиях Windows 10, мы попадаем в раздел «Представление задач». Здесь можно не только переключаться между приложениями, но и воспользоваться «Временной шкалой» и «Виртуальными рабочими столами». К слову, вместо горячих клавиш вы можете кликнуть по кнопке «Представление задач» (обычно она расположена рядом с кнопкой «Пуск») или провести пальцем от левого края к центру сенсорного экрана. Кстати, если у вас современный ноутбук – попробуйте жест для тачпада: проведите по нему тремя пальцами вверх.
Режим Представление задач
«Временная шкала»
«Временная шкала» появилась в Windows 10 два года назад. Она помогает вернуться к задачам, над которыми вы работали ранее на вашем компьютере. При необходимости вы также сможете синхронизировать ее и с другими устройствами с вашей учетной записью*.
Для меня «Временная шкала» стала своеобразной машиной времени. Работа над многими проектами длится несколько дней. И если, допустим, в прошлую пятницу я работал с определенными сайтами и документами, вернувшись к этому проекту в среду, я смогу легко восстановить картину. Я просто отмотаю шкалу до нужной даты – той самой пятницы, увижу и смогу открыть те самые сайты и документы, в которые я тогда был погружен.
Поиск на Временной шкале
Поиск на «Временной шкале» тоже не раз меня выручал. В отличие от обычного поиска по файлам, я смогу искать не среди всех документов на устройстве (а их может быть очень много), а именно среди тех, с которыми я работал в последние дни. Возможно, вам знакомо сочетание Ctrl + F, запускающее поиск в Проводнике и во многих приложениях. Эта комбинация сработает и на экране «Представление задач»: то есть можно нажать сначала Windows + Tab, а затем – Ctrl + F и ввести искомое слово для поиска по «Временной шкале».
* Подробная справка по настройкам «Временной шкалы».
Виртуальные рабочие столы Windows 10
Концепция виртуальных рабочих столов далеко не нова. Если говорить о Windows, то одним из вариантов их использования была утилита Desktops, которую когда-то (последняя версия вышла в 2012 году) разработал Марк Руссинович. В Windows 10 виртуальные рабочие столы встроены в систему и помогают разделять потоки задач, переключаться между ними.
Если раньше вы не работали с виртуальными столами, для понимания их логики представьте такую аналогию: вам доступно несколько мониторов, на каждом вы можете открыть нужные программы, разделив их по рабочим потокам, например: на одном мониторе – работа с почтой и календарем, на другом – работа с несколькими документами Word, а на третьем – работа с браузером и OneNote. В каждый момент вы смотрите только на один монитор (виртуальный рабочий стол) со своим набором приложений. А переключаясь между виртуальными столами, вы как будто переводите взгляд с одного монитора на другой.
Перетаскивание окна для переноса его на новый виртуальный рабочий стол
Создать новый виртуальный рабочий стол можно на экране «Представление задач»: нажмите Windows + Tab и перетащите нужные окна открытых приложений на поле с надписью «+ Создать рабочий стол», и они будут перемещены на другой виртуальный рабочий стол. Можно также создать новый, пустой виртуальный стол (Windows + Ctrl + D) и уже затем открыть на нем нужные программы.
«Переводить взгляд» (то есть переключаться между настроенными рабочими столами) можно, выбирая нужный стол на экране «Представление задач», но намного удобнее переключаться с помощью горячих клавиш: Windows + Ctrl + стрелки вправо/влево, а на современных тачпадах – 4 пальца влево или вправо.
Полезные решения для работы с несколькими приложениями
Теперь еще об одной повседневной необходимости – работе с несколькими приложениями одновременно.
Разделение экрана
Первой возможности, о которой хочу напомнить, уже много лет, и в первоначальном виде (под названием Aero Snap) она появилась еще в Windows 7. В Windows 10 ее возможности расширили и назвали Snap Assist. Речь про разделение экрана для закрепления двух (а в Windows 10 – до четырех) приложений.
Snap Assist предлагает выбрать второе окно для закрепления справа
Чтобы это сделать, нужно взять приложение за самую верхнюю полоску, поднести его к правой или левой границе экрана до появления на экране его «тени» и отпустить (тем самым, закрепив первое приложение), а затем в появившихся рядом миниатюрах других приложений выбрать второе для закрепления рядом. Сценарий несложный, работает и для мыши, и для пальца. Еще проще это можно сделать с помощью сочетания клавиш Windows + клавиши со стрелками вправо/влево. Этому сочетанию уже больше 10 лет, но у тех, кто применяет его впервые, и сейчас порой возникает ощущение «цифровой магии».
Любознательным пользователям также напомню, что в Windows 10 можно отправлять приложение в «четвертинку» экрана, перенеся его в угол (или используя дополнительно клавиши Windows + стрелки вверх/вниз). При закреплении двух приложений можно перемещать границу между ними, выделяя какому-то из приложений больше места. Чтобы выбрать приложения для закрепления на экране, можно кликнуть правой кнопкой мыши по их миниатюрам на экране «Представление задач».
Окно поверх
У меня было довольно мало ситуаций, когда требовалось закреплять окно одного приложения поверх другого (кажется, на телевизорах подобное называлось режимом «картинка в картинке»), но если у вас такая необходимость возникает, напомню в завершение заметки о двух небольших возможностях.
Мини-режим встроенного видеоплеера (приложение «Кино и ТВ», которое воспроизводит видео в Windows 10 по умолчанию). Запустите видео и нажмите на небольшую кнопку в правом нижнем углу (Воспроизвести в мини-режиме), окно с видеороликом будет размещено поверх всех окон.
Видео в режиме Окно поверх
Аналогичную возможность, только с закреплением поверх всех приложений окна браузера, можно получить с использованием отдельных утилит. Однажды мне потребовалось работать над документом, постоянно сверяясь при этом с сайтом одного онлайн-сервиса, и меня выручило приложение Always on Top, доступное в Microsoft Store. Оно встраивается в меню «Поделиться» в Edge и позволяет отправить любой сайт в окно, расположенное поверх всех приложений. Я мог бы пошутить, что этот вариант отлично подошел бы для просмотра каналов на YouTube «одним глазком» во время работы, например, над сводными таблицами в Excel. Но как мы и обсуждали в первой заметке, такая многозадачность скорее повредит и просмотру, и работе.
В этом обзоре я поделился некоторыми возможностями при работе с одной или несколькими задачами, которыми пользуюсь сам. В следующих заметках продолжу разговор о приемах, которые помогут сделать нашу «цифровую жизнь» более продуктивной.
Только зарегистрированные пользователи могут участвовать в опросе. Войдите, пожалуйста.
Сколько из лайфхаков вы использовали?
47.12% 2-3. И они пригождаются49
9.62% Ни одного (и теперь это в прошлом)10
30.77% Сижу на Linux/MacOS32
Проголосовали 104 пользователя. Воздержались 10 пользователей.
Многозада́чность (англ. multitasking) — свойство операционной системы или среды программирования обеспечивать возможность параллельной (или псевдопараллельной) обработки нескольких процессов. Истинная многозадачность операционной системы возможна только в распределённых вычислительных системах.
Существует 2 типа многозадачности[1]:
- Процессная многозадачность (основанная на процессах — одновременно выполняющихся программах). Здесь программа — наименьший элемент кода, которым может управлять планировщик операционной системы. Более известна большинству пользователей (работа в текстовом редакторе и прослушивание музыки).
- Поточная многозадачность (основанная на потоках). Наименьший элемент управляемого кода — поток (одна программа может выполнять 2 и более задачи одновременно).
Многопоточность — специализированная форма многозадачности[1].
Содержание
- 1 Свойства многозадачной среды
- 2 Трудности реализации многозадачной среды
- 3 История многозадачных операционных систем
- 4 Типы псевдопараллельной многозадачности
- 4.1 Невытесняющая многозадачность
- 4.2 Совместная или кооперативная многозадачность
- 4.3 Вытесняющая или приоритетная многозадачность (режим реального времени)
- 5 Проблемные ситуации в многозадачных системах
- 5.1 Голодание (starvation)
- 5.2 Гонка (race condition)
- 5.3 Инверсия приоритета
- 6 Ссылки
- 7 Примечания
[править] Свойства многозадачной среды
Примитивные многозадачные среды обеспечивают чистое «разделение ресурсов», когда за каждой задачей закрепляется определённый участок памяти, и задача активизируется в строго определённые интервалы времени.
Более развитые многозадачные системы проводят распределение ресурсов динамически, когда задача стартует в памяти или покидает память в зависимости от её приоритета и от стратегии системы. Такая многозадачная среда обладает следующими особенностями:
- Каждая задача имеет свой приоритет, в соответствии с которым получает процессорное время и память
- Система организует очереди задач так, чтобы все задачи получили ресурсы, в зависимости от приоритетов и стратегии системы
- Система организует обработку прерываний, по которым задачи могут активироваться, деактивироваться и удаляться
- По окончании положенного кванта времени ядро временно переводит задачу из состояния выполнения в состояние готовности, отдавая ресурсы другим задачам. При нехватке памяти страницы невыполняющихся задач могут быть вытеснены на диск (своппинг), а потом через определённое системой время, восстанавливаться в памяти
- Система обеспечивает защиту адресного пространства задачи от несанкционированного вмешательства других задач
- Система обеспечивает защиту адресного пространства своего ядра от несанкционированного вмешательства задач
- Система распознаёт сбои и зависания отдельных задач и прекращает их
- Система решает конфликты доступа к ресурсам и устройствам, не допуская тупиковых ситуаций общего зависания от ожидания заблокированных ресурсов
- Система гарантирует каждой задаче, что рано или поздно она будет активирована
- Система обрабатывает запросы реального времени
- Система обеспечивает коммуникацию между процессами
[править] Трудности реализации многозадачной среды
Основной трудностью реализации многозадачной среды является её надёжность, выраженная в защите памяти, обработке сбоев и прерываний, предохранении от зависаний и тупиковых ситуаций.
Кроме надёжности, многозадачная среда должна быть эффективной. Затраты ресурсов на её поддержание не должны: мешать процессам проходить, замедлять их работу, резко ограничивать память.
[править] История многозадачных операционных систем
Поначалу реализация многозадачных операционных систем представляла собой серьёзную техническую трудность, отчего внедрение многозадачных систем затягивалось, а пользователи долгое время после внедрения предпочитали однозадачные.
В дальнейшем, после появления нескольких удачных решений, многозадачные среды стали совершенствоваться, и в настоящее время употребляются повсеместно.
Впервые многозадачность операционной системы была реализована в ходе разработки операционной системы Multics (1964 год). Одной из первых многозадачных систем была OS/360 (1966[2]), используемая для компьютеров фирмы IBM и их советских аналогов ЕС ЭВМ. Разработки системы были сильно затянуты, и на начальное время фирма IBM выдвинула однозадачный DOS, чтобы удовлетворить заказчиков до полной сдачи OS/360 в эксплуатацию. Система подвергалась критике по причине малой надёжности и трудности эксплуатации.
В 1969 году на основе Multics была разработана система UNIX с достаточно аккуратным алгоритмическим решением проблемы многозадачности. В настоящее время на базе UNIX созданы десятки операционных систем.
На компьютерах PDP-11 и их советских аналогах СМ-4 использовалась многозадачная система RSX-11 (советский аналог — ОСРВ СМ ЭВМ), и система распределения времени TSX-PLUS, обеспечивающая ограниченные возможности многозадачности и многопользовательский режим разделения времени, эмулируя для каждого пользователя однозадачную RT-11 (советский аналог — РАФОС). Последнее решение было весьма популярно из-за низкой эффективности и надёжности полноценной многозадачной системы.
Аккуратным решением оказалась операционная система VMS, разработанная первоначально для компьютеров VAX (советский аналог — СМ-1700) как развитие RSX-11.
Первый в мире мультимедийный персональный компьютер Amiga 1000 (1984 год) изначально проектировался с расчётом на полную аппаратную поддержку вытесняющей многозадачности реального времени в ОС AmigaOS. В данном случае разработка аппаратной и программной части велась параллельно, это привело к тому, что по показателю квантования планировщика многозадачности (1/50 секунды на переключение контекста) AmigaOS долгое время оставалась непревзойдённой на персональных компьютерах.
Многозадачность обеспечивала также фирма Microsoft в операционных системах Windows. При этом Microsoft выбрала две линии разработок — на базе приобретённой ею Windows 0.9[источник не указан 1344 дня], которая после долгой доработки системы, изначально обладавшей кооперативной многозадачностью, аналогичной Mac OS, вылилась в линейку Windows 3.x, и на основе идей, заложенных в VMS, которые привели к созданию операционных систем Windows NT. Использование опыта VMS обеспечило системам существенно более высокую производительность и надёжность. По времени переключения контекста многозадачности (квантование) только эти операционные системы могут быть сравнимы с AmigaOS и UNIX (а также его потомками, такими, как ядро Linux).
Интересно, что многозадачность может быть реализована не только в операционной, но и языковой среде. Например, спецификации языков программирования Modula-2 и Ada требуют поддержки многозадачности вне привязки к какой-либо операционной системе. В результате, популярная в первой половине 1990-х годов реализация языка программирования TopSpeed Модула-2 от JPI/Clarion позволяла организовывать различные типы многозадачности (кооперативную и вытесняющую — см. ниже) для потоков одной программы в рамках такой принципиально однозадачной операционной системы, как MS-DOS. Это осуществлялось путём включения в модуль программы компактного планировщика задач, содержащего обработчик таймерных прерываний [3]. Языки программирования, обладающие таким свойством, иногда называют языками реального времени[4].
[править] Типы псевдопараллельной многозадачности
[править] Невытесняющая многозадачность
Тип многозадачности, при котором операционная система одновременно загружает в память два или более приложений, но процессорное время предоставляется только основному приложению. Для выполнения фонового приложения оно должно быть активизировано. Подобная многозадачность может быть реализована не только в операционной системе, но и с помощью программ-переключателей задач. В этой категории известна программа DESQview, работавшая под DOS и выпущенная первый раз в 1985 году.
[править] Совместная или кооперативная многозадачность
Тип многозадачности, при котором следующая задача выполняется только после того, как текущая задача явно объявит себя готовой отдать процессорное время другим задачам. Как частный случай, такое объявление подразумевается при попытке захвата уже занятого объекта mutex (ядро Linux), а также при ожидании поступления следующего сообщения от подсистемы пользовательского интерфейса (Windows версий до 3.x включительно, а также 16-битные приложения в Windows 9x).
Кооперативную многозадачность можно назвать многозадачностью «второй ступени» поскольку она использует более передовые методы, чем простое переключение задач, реализованное многими известными программами (например, DOS Shell из MS-DOS 5.0 при простом переключении активная программа получает все процессорное время, а фоновые приложения полностью замораживаются. При кооперативной многозадачности приложение может захватить фактически столько процессорного времени, сколько оно считает нужным. Все приложения делят процессорное время, периодически передавая управление следующей задаче.
Преимущества кооперативной многозадачности: отсутствие необходимости защищать все разделяемые структуры данных объектами типа критических секций и mutex’ов, что упрощает программирование, особенно перенос кода из однозадачных сред в многозадачные.
Недостатки: неспособность всех приложений работать в случае ошибки в одном из них, приводящей к отсутствию вызова операции «отдать процессорное время». Крайне затрудненная возможность реализации многозадачной архитектуры ввода-вывода в ядре ОС, позволяющей процессору исполнять одну задачу в то время, как другая задача инициировала операцию ввода-вывода и ждет её завершения.
Реализована в пользовательском режиме ОС Windows версий до 3.х включительно, Mac OS версий до Mac OS X, а также внутри ядер многих UNIX-подобных ОС, таких, как FreeBSD, а в течение долгого времени — и Linux.
[править] Вытесняющая или приоритетная многозадачность (режим реального времени)
Вид многозадачности, в котором операционная система сама передает управление от одной выполняемой программы другой в случае завершения операций ввода-вывода, возникновения событий в аппаратуре компьютера, истечения таймеров и квантов времени, или же поступлений тех или иных сигналов от одной программы к другой. В этом виде многозадачности процессор может быть переключен с исполнения одной программы на исполнение другой без всякого пожелания первой программы и буквально между любыми двумя инструкциями в её коде. Распределение процессорного времени осуществляется планировщиком процессов. К тому же каждой задаче может быть назначен пользователем или самой операционной системой определенный приоритет, что обеспечивает гибкое управление распределением процессорного времени между задачами (например, можно снизить приоритет ресурсоёмкой программе, снизив тем самым скорость её работы, но повысив производительность фоновых процессов). Этот вид многозадачности обеспечивает более быстрый отклик на действия пользователя.
Преимущества: возможность полной реализации многозадачного ввода-вывода в ядре ОС, когда ожидание завершения ввода-вывода одной программой позволяет процессору тем временем исполнять другую программу. Сильное повышение надежности системы в целом, в сочетании с использованием защиты памяти — идеал в виде «ни одна программа пользовательского режима не может нарушить работу ОС в целом» становится достижимым хотя бы теоретически, вне вытесняющей многозадачности он не достижим даже в теории. Возможность полного использования многопроцессорных и многоядерных систем.
Недостатки: необходимость особой дисциплины при написании кода, особые требования к его реентрантности, к защите всех разделяемых и глобальных данных объектами типа критических секций и mutex’ов.
Реализована в таких ОС, как:
- VMS
- Linux
- в пользовательском режиме (а часто и в режиме ядра) всех UNIX-подобных ОС, включая версии Mac OS X, iOS; Symbian OS
- в режиме ядра ОС Windows 3.x — только при исполнении на процессоре 386 или старше, «задачами» являются только все Windows-приложения вместе взятые и каждая отдельная виртуальная машина ДОС, между приложениями Windows вытесняющая многозадачность не использовалась
- Windows 95/98/ME — без полноценной защиты памяти, что служило причиной крайне низкой, на одном уровне с MS-DOS, Windows 3.x и Mac OS версий до X — надежности этих ОС
- Windows NT/2000/XP/Vista/7 и в режиме ядра, и в пользовательском режиме.
- AmigaOS — все версии, до версии 4.0 без полноценной защиты памяти, что на практике для системных программ почти не сказывалось на надёжности из-за высокой стандартизированности, прозрачных API и SDK. Программы ориентированные на «железо» Амиги, наоборот не отличались надёжностью.
[править] Проблемные ситуации в многозадачных системах
[править] Голодание (starvation)
Задержка времени от пробуждения потока до его вызова на процессор, в течение которой он находится в списке потоков, готовых к исполнению. Возникает по причине присутствия потоков с большими или равными приоритетами, которые исполняются все это время.
Негативный эффект заключается в том, что возникает задержка времени от пробуждения потока до исполнения им следующей важной операции, что задерживает исполнение этой операции, а следом за ней и работу многих других компонентов.
Голодание создаёт узкое место в системе и не дает выжать из неё максимальную производительность, ограничиваемую только аппаратно обусловленными узкими местами.
Любое голодание вне 100 % загрузки процессора может быть устранено повышением приоритета голодающей нити, возможно — временным.
Как правило, для предотвращения голодания ОС автоматически вызывает на исполнение готовые к нему низкоприоритетные потоки даже при наличии высокоприоритетных, при условии, что поток не исполнялся в течение долгого времени (~10 секунд). Визуально эта картина хорошо знакома большинству пользователей Windows — если в одной из программ поток зациклился до бесконечности, то переднее окно работает нормально несмотря на это — потоку, связанному с передним окном, Windows повышает приоритет. Остальные же окна перерисовываются с большими задержками, по порции в секунду, ибо их отрисовка в данной ситуации работает только за счет механизма предотвращения голодания (иначе бы голодала вечно).
[править] Гонка (race condition)
Недетерминированный порядок исполнения двух путей кода, работающих с одними и теми же данными и исполняемыми в двух различных нитях. Приводит к зависимости порядка и правильности исполнения от случайных факторов.
Устраняется добавлением необходимых блокировок и примитивов синхронизации. Обычно является легко устраняемым дефектом (забытая блокировка).
[править] Инверсия приоритета
Поток L имеет низкий приоритет, поток M — средний, поток H — высокий. Поток L захватывает mutex, и, выполняясь с удержанием mutex’а, преемптивно прерывается потоком M, который пробудился по какой-то причине, и имеет более высокий приоритет. Поток H пытается захватить mutex.
В полученной ситуации поток H ожидает завершения текущей работы потоком M, ибо, пока поток M исполняется, низкоприоритетный поток L не получает управления и не может освободить mutex.
Устраняется повышением приоритета всех нитей, захватывающих данный mutex, до одного и того же высокого значения на период удержания mutexa. Некоторые реализации mutex’ов делают это автоматически.
[править] Ссылки
- Аппаратная поддержка мультипрограммирования на примере процессора Pentium
[править] Примечания
- ↑ 1 2 [Герберт Шилдт «Полный справочник по Java», 7-е издание.:Пер. с англ.-М.:ООО «И. Д. Вильямс», 2007, стр. 253—254]
- ↑ Mealy G. H., Witt B. I., Clark W. A. The functional structure of OS/360. IBM Systems Journal, 5, № 1, 1966
- ↑ Белецкий Я. ТопСпид: Расширенная версия языка Модула-2 для персональных компьютеров IBM. — М.: «Машиностроение», 1993
- ↑ Янг С. Алгоритмические языки реального времени
Аспекты операционных систем (история • список) | |
---|---|
Ядро |
Гибридное • Микро • Модульное • Монолитное • Нано • Экзо • Драйвер • Пространство пользователя • Область пользователя |
Управление процессами |
Режимы (супервизора • реальный • защищённый) • Прерывание • Кольца защиты • Переключение контекста • Многозадачность (вытесняющая • кооперативная • мультипрограммирование) • Процесс • Управление процессом • Планировщик задач • Многопоточность |
Управление памятью |
Защита памяти • Сегментная адресация памяти • Страничная память • Менеджер виртуальной памяти • Ошибка сегментации • Общая ошибка защиты |
Прочее |
Загрузчик ОС • API • VFS • Компьютерная сеть • GUI • Слой аппаратных абстракций (HAL) |
Многозадачность — способность операционной системы (или программного окружения) поддерживать одновременное совместное выполнение и взаимодействие нескольких задач (программ, потоков исполнения) друг с другом и внешней средой.
Если система может выполнять задачи только последовательно, начиная следующую только после завершения текущей, то система называется однозадачной. Первые системы были именно такими.
Переходным звеном к многозадачным ОС является ОС пакетной обработки: будучи однозадачной по сути, такая система работает не с одним приложением, а потоком пакетов, которые последовательно обрабатывает (запуская функции или программы их обработки).
Непосредственно же о многозадачности следует говорить тогда, когда окружение обеспечивает наличие в системе одновременно нескольких потоков исполнения.
Идеальным случаем многозадачности является параллельная многозадачность, когда каждая задача исполняется в своём аппаратном микропроцессорном ядре действительно одновременно друг с другом. Такой вариант даже реализован, например в микроконтроллере Propeller от Parallax (обеспечивает работу сразу 8 задач), однако обычно использование отдельных аппаратных средств под каждую задачу оказывается слишком расточительным, поэтому применяется псевдопараллельная многозадачность, когда ресурсы микропроцессора поочерёдно передаются между задачами, создавая иллюзию одновременности, или совокупность параллельной и псевдопараллельной многозадачности при наличии нескольких процессорных ядер.
Различают два основных типа псевдопараллельной многозадачности:
- невытесняющая — требующая явной передачи управления между задачами в определённых точках по их инициативе;
- вытесняющая — в которой переключение между задачам происходит неявно, посредством диспетчера задач в произвольные моменты времени.
Невытясняющая многозадачность, как наиболее примитивная, была создана первой и имеет свои достинства и недостатки:
- + весьма легка в реализации;
- + хорошо предсказуема в поведении, исключает многие опасные ситуации, такие как гонки за использование разделяемых ресурсов;
- + предъявляет минимум требований к системе и тратит минимум ресурсов (возможно даже использование несколькими задачами одного стека);
- — требует особого стиля написания программ, затрудняя как разработку новых, так и адаптацию существующих;
- — затруднена оперативная реакция на внешние события;
- — практически невозможна защита задач друг от друга, что сильно снижает надёжность системы — как правило одна неправильно работающая задача легко заваливает все остальные (блокирует или нарушает их работу).
В противоположность ей существует вытесняющая задачность. В ней организация взаимодействия между полностью возложена на программное окружение (а конкретно, диспетчер задач), позволяя нескольким задачам одновременно работать в системе так, как если бы каждая была единственной. При этом возможно вытеснение задачи в любой момент времени и в любой точке кода (за исключением мест, где это явно запрещено) с переключением на другую. Плюсы и минусы следующие:
- + не требует от задач заботы о переключении между ними, любая задача, пока от неё не требуется взаимодействия с другими задачами или пользоватлься общими ресурсами может выглядеть так же, как если бы она была в однозадачном окружении;
- + задача может оперативно получить управление в случае необходимости вне зависимости от состояния других задач, что обеспечивает работу в реальном времени;
- + широки возможности реализации защиты операционной системой задач от ошибок и атак;
- — требует специальных методов синхронизации задач друг с другом во избежание неопределённых ситуаций и конфликтов;
- — нуждается в поддержке со стороны аппаратного обеспечения (как минимум для сохранения и восстановления состояния микропроцесора при переключении);
- — требует больше системных ресурсов (память под стек и сохранение состояния для каждого процессора и время на переключение контекстов).
Невытесняющая многозадачность
Достоинства вытесняющей многозадачности оказываются наиболее существенными для большинства практических задач и поэтому практически все достаточно развитые современные операционные системы реализуют именно этот тип многозадачности.
Эффективность многозадачной системы во многом зависит от способа диспетчеризации задач на исполнение. Для понимания диспетчеризации важным является понятие состояния задачи. Основные состояния задач такие:
- выполняется;
- готова к исполнению;
- заблокирована.
Задача находится в состоянии исполнения тогда, когда под неё выделен ресурс процессора и передано управление. Очевидно, что в системе не может быть выполняющихся задач больше, чем физических процессоров. Поэтому существует второе состояние — готовность к исполнению. Задача в это состояние тогда, когда она может исполняться, то есть не существует причин, вызывающих блокировку, но вычислительные ресурсы отданы под другие задачи. В третье состояние задача попадает при невозможности её исполнения в данный момент времени. Это может быть
- ожидание какого либо события (открытия семафора, прихода сообщения и т. п.);
- незавершённая инициализация (когда ещё не созданы другой задачей или системой начальные условия для запуска);
- «заморозка» (явная остановка исполнения, обычно в отладочных целях);
- завершение (состояние «зомби», когда исполнение уже закончено, но ресурсы ещё не освобождены);
- или какие-то ещё специфические случаи.
Многие оперционные системы рассматривают эти случаи как различные, однако они имеют отражаются лишь в деталях реализации.
В отличие от первых двух, состояние блокировки, вообще говоря не является обязательным. Достаточно стандартным является лишь случай ожидания, ходя и его можно реализовать пустым циклом. Однако это является пустой тратой процессорного времени, которое можно занять другой задачей, поэтому состояние блокировки существует практически во всех многозадачных ОС.
Известно несколько основных стратегий диспетчеризации:
- круговая (round-robin)
- управление между задачами производится в в каком-либо фиксированном порядке через определённые промежутки времени;
- случайная (random)
- через каждый определённый промежуток времени управление передаётся на произвольную задачу;
- приоритетная (priority-driven)
- каждая задача имеет уровень приоритета и управление получает незаблокированная задача имеющая наибольший уровень;
- (deadline-driven)
- передача управления производится в порядке, обеспечивающем выполнение задач в определённый срок.