Министерство транспорта РФ

Федеральное агентство железнодорожного транспорта

ГОУ ВПО "ДВГУПС"

Кафедра: "Информационные технологии и системы"

КУРСОВАЯ РАБОТА

на тему: "Подсистема управления процессами"

Выполнил: Шолков И.Д.

группа 230

Проверил: Решетникова О.В.

Хабаровск 2010

Введение

1. Описание программы

1.1 Функциональное назначение

1.2 Технические средства, используемые при создании программы

1.3 Многопоточность и многопроцессорность

1.4 Приоритеты потоков и процессов

1.5 Способы синхронизации потоков

1.3 Логическая структура программы

2. Руководство пользователя по работе с программой

2.1 Общие сведения и назначение программы

2.2 Графический интерфейс

2.3 Работа с программой

2.4 Основные характеристики программы ProcessManager

Заключение

Список литературы

C# поддерживает параллельное выполнение кода через многопоточность. Поток – это независимый путь исполнения, способный выполняться одновременно с другими потоками.

Программа на C# запускается как единственный поток, автоматически создаваемый CLR и операционной системой ("главный" поток), и становится многопоточной при помощи создания дополнительных потоков.

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

На однопроцессорных компьютерах планировщик потоков использует квантование времени – быстрое переключение между выполнением каждого из активных потоков. Это приводит к непредсказуемому поведению, как в самом первом примере, где каждая последовательность символов ‘X’ и ‘Y’ соответствует кванту времени, выделенному потоку. В Windows XP типичное значение кванта времени – десятки миллисекунд – выбрано как намного большее, чем затраты CPU на переключение контекста между потоками (несколько микросекунд).

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

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

Все потоки одного приложения логически содержатся в пределах процесса – модуля операционной системы, в котором исполняется приложение.

В некоторых аспектах потоки и процессы схожи – например, время разделяется между процессами, исполняющимися на одном компьютере, так же, как между потоками одного C#-приложения. Ключевое различие состоит в том, что процессы полностью изолированы друг от друга. Потоки разделяют память (кучу) с другими потоками этого же приложения. Благодаря этому один поток может поставлять данные в фоновом режиме, а другой – показывать эти данные по мере их поступления.

Свойство Priority определяет, сколько времени на исполнение будет выделено потоку относительно других потоков того же процесса. Существует 5 градацийприоритетапотока:enum ThreadPriority { Lowest, BelowNormal, Normal, AboveNormal, Highest }

Значение приоритета становится существенным, когда одновременно исполняются несколько потоков.

Установка приоритета потока на максимум еще не означает работу в реальном времени (real-time), так как существуют еще приоритет процесса приложения. Чтобы работать в реальном времени, нужно использовать класс Process из пространства имен System.Diagnostics для поднятия приоритета процесса.

От ProcessPriorityClass.High один шаг до наивысшего приоритета процесса – Realtime. Устанавливая приоритет процесса в Realtime, вы говорите операционной системе, что хотите, чтобы ваш процесс никогда не вытеснялся. Если ваша программа случайно попадет в бесконечный цикл, операционная система может быть полностью заблокирована. Спасти вас в этом случае сможет только кнопка выключения питания. По этой причине ProcessPriorityClass.High считается максимальным приоритетом процесса, пригодным к употреблению.

Если real-time приложение имеет пользовательский интерфейс, может быть не желательно поднимать приоритет его процесса, так как обновление экрана будет съедать чересчур много времени CPU – тормозя весь компьютер, особенно если UI достаточно сложный.

Оператор lock (aka Monitor.Enter/Monitor.Exit) – один из примеров конструкций синхронизации потоков. Lock является самым подходящим средством для организации монопольного доступа к ресурсу или секции кода, но есть задачи синхронизации (типа подачи сигнала начала работы ожидающему потоку), для которых lock будет не самым адекватным и удобным средством.

В Win32 API имеется богатый набор конструкций синхронизации, и они доступны в.NET Framework в виде классов EventWaitHandle, Mutex и Semaphore. Некоторые из них практичнее других: Mutex, например, по большей части дублирует возможности lock, в то время как EventWaitHandle предоставляет уникальные возможности сигнализации.

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

EventWaitHandle имеет два производных класса – AutoResetEvent и ManualResetEvent (не имеющие никакого отношения к событиям и делегатам C#). Обоим классам доступны все функциональные возможности базового класса, единственное отличие состоит в вызове конструктора базового класса с разными параметрами.

В части производительности, все WaitHandle обычно исполняются в районе нескольких микросекунд. Это редко имеет значение с учетом контекста, в котором они применяются.

AutoResetEvent – наиболее часто используемый WaitHandle-класс и основная конструкция синхронизации, наряду с lock.

AutoResetEvent очень похож на турникет – один билет позволяет пройти одному человеку. Приставка "auto" в названии относится к тому факту, что открытый турникет автоматически закрывается или "сбрасывается" после того, как позволяет кому-нибудь пройти. Поток блокируется у турникета вызовом WaitOne (ждать (wait) у данного (one) турникета, пока он не откроется), а билет вставляется вызовом метода Set. Если несколько потоков вызывают WaitOne, за турникетом образуется очередь. Билет может "вставить" любой поток – другими словами, любой (неблокированный) поток, имеющий доступ к объекту AutoResetEvent, может вызвать Set, чтобы пропустить один блокированный поток.

Если Set вызывается, когда нет ожидающих потоков, хэндл будет находиться в открытом состоянии, пока какой-нибудь поток не вызовет WaitOne. Эта особенность помогает избежать гонок между потоком, подходящим к турникету, и потоком, вставляющим билет ("опа, билет вставлен на микросекунду раньше, очень жаль, но вам придется подождать еще сколько-нибудь!"). Однако многократный вызов Set для свободного турникета не разрешает пропустить за раз целую толпу – сможет пройти только один человек, все остальные билеты будут потрачены впустую.

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

Метод Reset обеспечивает закрытие открытого турникета, безо всяких ожиданий и блокировок.

AutoResetEvent может быть создан двумя путями. Во-первых, с помощью своего конструктора:EventWaitHandle wh = new AutoResetEvent(false);

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

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

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

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

Подсистема управления процессами и потоками имеет возможность выполнять над процессами следующие операции:

– создание (порождение)/уничтожение процесса;

– приостановка/возобновление процесса;

– блокирование/пробуждение процесса;

– запуск процесса;

– изменение приоритета процесса;

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

1. Создание и удаление процессов и потоков

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

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

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

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

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

2. Планирование и диспетчеризация процессов и потоков

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

– по возможности заканчивать вычисления в том же самом порядке, в каком они были начаты;

– отдавать предпочтение более коротким процессам;

– предоставлять всем пользователям (задачам пользователей) одинаковые услуги, в том числе и одинаковое время ожидания.

На протяжении существования процесса выполнение его потоков может быть многократно прервано и продолжено.

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

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

В различных информационных источниках существуют различные трактовки понятий "планирование" и "диспетчеризация". Так, некоторые авторы планирование подразделяют на долгосрочное (глобальное) и краткосрочное (динамическое, т.е. текущее наиболее эффективное распределение), и последнее называют диспетчеризацией. Согласно другим источникам, под диспетчеризацией понимают реализацию принятого на этапе планирования решения. Мы будем придерживаться этого варианта.

Планирование включает в себя решение двух задач:

определение момента времени для смены активного потока;

выбор для выполнения потока из очереди готовых потоков.

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

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

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

Диспетчеризация заключается в реализации найденного в результате планирования решения, т.е. в переключении одного процесса на другой. Диспетчеризация сводится к следующему:

сохранение контекста текущего потока, который требуется сменить;

запуск нового потока на выполнение.

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

В контексте потока можно выделить часть, общую для всех потоков данного процесса (ссылки на открытые файлы), и часть, относящуюся только к данному потоку (содержимое регистров, счетчик команд, режим процессора). Например, в среде NetWare различаются три вида контекстов – глобальный контекст (контекст процесса), контекст группы потоков и контекст отдельного потока. Соотношение между данными этих контекстов аналогично соотношению глобальных и локальных переменных в программе. Иерархическая организация контекстов ускоряет переключение потоков: при переключении с потока одной группы на поток другой группы в пределах одного процесса глобальный контекст не изменяется, а меняется лишь контекст группы. Переключение глобальных контекстов происходит только при переходе с потока одного процесса на поток другого процесса.

3. Алгоритмы планирования

С точки зрения решения первой задачи планирования (выбор момента времени для смены активного потока) алгоритмы планирования делятся на два больших класса – вытесняющие и невытесняющие алгоритмы:

невытесняющие – активный поток может выполняться до тех пор, пока он сам не передаст управление системе, чтобы та выбрала из очереди другой готовый поток;

вытесняющие – операционная система принимает решение о смене выполняемого задания и переключает процессор на другой поток.

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

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

Достоинства данного подхода:

– исключено прерывание потока в неудобный для него момент;

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

– более высокая скорость переключения с потока на поток.

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

Вытесняющие алгоритмы – циклический, или круговой тип планирования, при котором операционная система сама решает вопрос о прерывании активного приложения и переключает процессор с одной задачи на другую в соответствии с тем или иным критерием. В системе с такими алгоритмами программисту не надо заботиться о том, что его приложение будет выполняться одновременно с другими задачами. В качестве примеров можно назвать операционные системы UNIX, Windows NT/2000, OS/2. Алгоритмы этого класса ориентированы на высокопроизводительное выполнение приложений.

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

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

При выделении квантов потоку могут использоваться разные принципы: эти кванты могут быть фиксированной величины или изменяться в разные периоды жизни потока. Например, для некоторого конкретного потока первый квант может быть довольно большим, а каждый следующий выделяемый ему квант может иметь меньшую длительность (уменьшение до заданных пределов). Таким образом формируется преимущество для более коротких потоков, а длительные задачи переходят в фоновый режим. Другой принцип основан на том факте, что процессы, часто выполняющие операции ввода-вывода, не полностью реализуют выделяемые им кванты времени. Для компенсации этой несправедливости из таких процессов может быть сформирована отдельная очередь, которая имеет привилегии по отношению к остальным потокам. При выборе очередного потока на выполнение сначала просматривается эта очередь, и, только если она пуста, выбирается поток из общей очереди готовых к выполнению.

Эти алгоритмы не используют никакой предварительной информации о задачах. Дифференциация обслуживания в данном случае базируется на "истории существования" потока в системе.

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

Теперь рассмотрим некоторые наиболее распространенные дисциплины планирования.


Обслуживание в порядке поступления . Выделение процессора производится по принципу FIFO (First In First Out), т.е. в порядке поступления заявок на обслуживание. Этот подход позволяет реализовать стратегию "по возможности заканчивать вычисления в порядке их появления". Те задачи, которые были заблокированы в процессе выполнения, после перехода в состояние готовности ставятся в очередь перед теми задачами, которые еще не выполнялись. Таким образом, создается две очереди: одна из еще не выполнявшихся задач, а другая – из задач, перешедших из состояния ожидания.

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

Достоинством данного алгоритма является его простота реализации. Недостатком – при большой загрузке короткие задания вынуждены ожидать в системе долгое время. Следующий подход устраняет этот недостаток.

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

Алгоритм относится к разряду невытесняющих бесприоритетных.

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


Карусельная дисциплина , или круговая RR (Round Robin). Данная дисциплина относится к вытесняющим алгоритмам и основана на квантовании. Каждая задача получает процессорное время порциями – квантами. После окончания кванта времени задача снимается с процессора и ставится в конец очереди процессов, готовых к выполнению, а на обслуживание процессором принимается очередная задача. Для оптимальной работы системы необходимо правильно выбрать закон, по которому кванты времени выделяются задачам.

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

В некоторых ОС есть возможность указывать в явном виде величину кванта времени или допустимый диапазон его значений. Например, в OS/2 в файле CONFIG.SYS с помощью оператора TIMESLICE указывается минимальное и максимальное значения для кванта времени: TIMESLICE=32,256 указывает, что квант возможно изменять в пределах от 32 до 256 миллисекунд.

Данная дисциплина обслуживания является одной из самых распространенных. В некоторых случаях, когда ОС не поддерживает в явном виде дисциплину карусельного планирования, такое обслуживание можно организовать искусственно. Например, в некоторых ОСРВ используется планирование с абсолютными приоритетами, а при равенстве приоритетов действует принцип очередности. Т.е., снять задачу с выполнения может только задача с более высоким приоритетом. При необходимости организовать обслуживание равномерно и равноправно, т.е. чтобы все задания получали одинаковые кванты времени, системный оператор может сам реализовать такое обслуживание. Для этого достаточно всем пользовательским задачам присвоить одинаковые приоритеты и создать одну высокоприоритетную задачу, которая не должна ничего делать, кроме как планироваться на выполнение по таймеру через указанные интервалы времени. Эта задача будет только снимать с выполнения текущее приложение, оно переместится в конец очереди, а сама задача тут же покинет процессор и уступит его следующему в очереди процессу.

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

Планирование согласно приоритетам .

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

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

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

Таким образом, приоритет может быть статическим (фиксированным) или динамическим (изменяющимся системой в зависимости от ситуации в ней). Так называемый базовый приоритет потока непосредственно зависит от базового приоритета процесса, его породившего. В некоторых случаях система может повышать приоритет потока (причем в различной степени), например, если квант отведенного ему процессорного времени не был использован полностью, или понижать приоритет в противном случае. Например, ОС повышает приоритет в большей степени потокам, ожидающим ввода с клавиатуры, и в меньшей степени – потокам, выполняющим операции с диском. В некоторых системах, использующих механизм динамических приоритетов, для изменения приоритета используются достаточно сложные формулы, в которых участвуют значения базовых приоритетов, степень загрузки вычислительной системы, начальное значение приоритета, заданное пользователем, и т.п.

Существуют две разновидности приоритетного планирования: обслуживание с относительными приоритетами и обслуживание с абсолютными приоритетами . В обоих случаях выбор потока на выполнение осуществляется одинаково – выбирается поток, имеющий наивысший приоритет, а момент смены активного потока определяется по-разному. В системе с относительными приоритетами активный поток выполняется до тех пор, пока он сам не покинет процессор (перейдет в состояние ожидания, или произойдет ошибка, или поток завершится). В системе с абсолютными приоритетами прерывание активного потока, кроме указанных причин, происходит еще и в случае, если в очереди готовых потоков появляется поток с более высоким приоритетом, чем активный. Тогда выполняемый поток прерывается и переводится в состояние готовности.

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

Смешанный тип планирования используется во многих ОС: алгоритмы планирования на основе приоритетов сочетаются с концепцией квантования.

Сердцем операционной системы UNIX является подсистема управления процессами. Практически все действия ядра имеют отношение к процессам, будь то обслуживание системного вызова, генерация сигнала, размещение памяти, обработка особых ситуаций, вызванных выполнением процесса или обеспечением услуг ввода/вывода по запросу прикладного процесса.
Вся функциональность операционной системы в конечном счете определяется выполнением тех или иных процессов, как и уровни выполнения системы (run levels) представляют собой ни что иное, как удобную форму определения группы выполняющихся процессов. Возможность терминального или сетевого доступа к системе, различные сервисы, традиционные для UNIX, - система печати, удаленные архивы FTP, электронная почта и система телеконференций (news) - все это результат выполнения определенных процессов. Процессы в UNIX неотъемлемо связаны с двумя важнейшими ресурсами системы процессором и оперативной памятью. Как правило, этих ресурсов никогда не бывает "много", и в операционной системе происходит активная конкурентная борьба за право обладания процессором и памятью. И по скольку UNIX является многозадачной системой общего назначения, задача справедливого распределения этого ресурса между задачами различного класса и с различными требованиями является нетривиальной.
По скольку запущенная на выполнение программа порождает в системе один или более
процессов (или задач). Подсистема управления процессами контролирует:
  • Создание и удаление процессов
  • Распределение системных ресурсов (памяти, вычислительных ресурсов) между процессами
  • Синхронизацию процессов
  • Межпроцессное взаимодействие
Очевидно, что в общем случае число активных процессов превышает число процессоров компьютера,
но в каждый конкретный момент времени на каждом процессоре может выполняться только один процесс. Операционная система управляет доступом процессов к вычислительным ресурсам,
создавая ощущение одновременного выполнения нескольких задач. Специальная задача ядра, называемая планировщиком процессов (scheduler), разрешает конфликты между процессами в конкуренции за системные ресурсы (процессор, память, устройства ввода/вывода). Планировщик запускает процесс на выполнение, следя за тем, чтобы процесс монопольно не захватил разделяемые системные ресурсы. Процесс освобождает процессор, ожидая длительной операции ввода/вывода, или по прошествии кванта времени. В этом случае планировщик выбирает следующий процесс с наивысшим приоритетом и запускает его на выполнение.

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

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

Основы управления процессом

Процесс UNIX представляет собой исполняемый образ программы, включающий отображение в памяти - исполняемого файла, полученного в результате компиляции, то есть трансляции модулей программы, языков высокого уровня, в эквивалентные программные модули языка низкого уровня, как то: стек, код и данные библиотек, а также ряд структур данных ядра, необходимых для управления процессом, что есть весьма важный момент для дальнейшего понимания принципов распределения памяти, как одного из важнейших ресурсов в "конкуренции" процессов, то есть данные -- структуированы!, условно на:
  • Stack (c тек ) - область памяти, в которой программа хранит информацию о вызываемых функциях, их аргументах и каждой локальной переменной в функциях. Размер области может меняться по мере работы программы. При вызове функций стек увеличивается, а при завершении - уменьшается.
  • Heap (к уча ) - это область памяти, в которой программа может делать всё, что угодно. Размер области может меняться. Программист имеет возможность воспользоваться частью памяти кучи с помощью функции malloc() , и тогда эта область памяти увеличивается. Возврат ресурсов осуществляется с помощью free() , после чего куча уменьшается.
  • Сode (к одовый сегмент ) - это область памяти, в которой хранятся машинные инструкции скомпилированной программы. Они генерируются компилятором, но могут быть написаны и вручную. Обратите внимание, что эта область памяти также может быть разделена на три части (текст, данные и BSS). Эта область памяти имеет фиксированный размер, определяемый компилятором. UNIX. Профессиональное программирование ст.259

Это в дальнейшем(в том числе) и предопределит возникновение(существование) сегментов и страниц. Процесс во время выполнения использует различные системные ресурсы - память, процессор, услуги файловой подсистемы и подсистемы ввода/вывода. Суровая правда любого современного вычислительного комплекса в том, что один процессор может обслуживать только один процесс в единицу времени, что в свою очередь предопределило возникновение(существование) "планировщика", по средствам которого операционная система UNIX обеспечивает иллюзию одновременного выполнения нескольких процессов, эффективно распределяя системные ресурсы между активными процессами и не позволяя в то же время ни одному из них монополизировать использование этих ресурсов.

Новорожденная операционная система UNIX обеспечивала выполнение всего двух процессов, по одному на каждый подключенный к PDP-7 терминал. Спустя год, на той же PDP-7 число процессов заметно увеличилось, появился системный вызов fork . В Первой редакции UNIX появился вызов ехес , но операционная система по прежнему позволяла размещать в памяти только один процесс в каждый момент времени. После реализации аппаратной подсистемы управления памятью на PDP-11 операционная система была модифицирована, что позволило загружать в память сразу несколько процессов, уменьшая тем самым время на сохранение образа процесса во вторичной памяти (на диске) и считывание его, когда процесс продолжал выполнение. Однако до 1972 года UNIX нельзя было назвать действительно многозадачной системой, т. к. операции ввода/вывода оставались синхронными, и другие процессы не могли выполняться, пока их "коллега" не завершал операцию ввода/вывода. Истинная многозадачность появилась только после того, как код UNIX был переписан на языке С в 1973 году. С тех пор основы управления процессами практически не изменились.


Выполнение процесса может происходить в двух режимах - в режиме ядра (kernel mode ) или в режиме задачи (user mode ). В режиме задачи процесс выполняет инструкции прикладной программы, допустимые на непривилегированном уровне защиты процессора. При этом процессу недоступны системные структуры данных. Когда процессу требуется получение каких либо услуг ядра, он делает системный вызов, который выполняет инструкции ядра, находящиеся на привилегированном уровне.

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

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

Структуры данных процесса

Каждый процесс представлен в системе двумя основными структурами данных proc и user ,

описанными, соответственно, в файлах sys/proc.h и sys/user.h . Содержимое и формат этих структур различны для разных версий UNIX.

....................................................................................................

https://m.habr.com/ru/company/*nix <-----------
….................................................................................................
В любой момент времени данные структур proc для всех процессов должны присутствовать в памяти, хотя остальные структуры данных, включая образ процесса, могут быть перемещены во вторичную память, область свопинга. Это позволяет ядру иметь под рукой минимальную информацию, необходимую для определения местонахождения остальных данных, относящихся к процессу, даже если они отсутствуют в памяти. Структура proc является записью системной таблицы процессов, которая, как мы только что заметили, всегда находится в оперативной памяти. Запись этой таблицы для выполняющегося в настоящий момент процесса адресуется системной переменной curproc. Каждый раз при переключении контекста, когда ресурсы процессора передаются другому
процессу, соответственно изменяется значение переменной curproc , которая теперь указывает на структуру proc активного процесса. Вторая упомянутая структура user , также называемая u-area или u-block , содержит дополнительные данные о процессе, которые требуются ядру только во время выполнения процесса (т. е. когда процессор выполняет инструкции процесса в режиме ядра или задачи). В отличие от структуры proc , адресованной указателем curproc , данные user размещаются
(точнее, отображаются) в определенном месте виртуальной памяти ядра и адресуются переменной u . Ниже показаны две основные структуры данных процесса и способы их адресации ядром UNIX.
В u-area хранятся данные, которые используются многими подсистемами ядра и не только для управления процессом. В частности, там содержится информация об открытых файловых дескрипторах, диспозиция сигналов, статистика выполнения процесса, а также сохраненные значения регистров, когда выполнение процесса приостановлено. Очевидно, что процесс не должен иметь возможности модифицировать эти данные произвольным образом, поэтому u-area защищена от доступа в режиме задачи. Как видно из рис., u-area также содержит стек фиксированного размера, системный стек или стек ядра (kernel stack). При выполнении процесса в режиме ядра операционная система использует этот стек, а не обычный стек процесса.

Состояния процесса

Жизненный цикл процесса может быть разбит на несколько состояний. Переход процесса из одного состояния в другое происходит в зависимости от наступления тех или иных событий в системе.
  • 1. Процесс выполняется в режиме задачи. При этом процессором выполняются прикладные инструкции данного процесса.
  • 2. Процесс выполняется в режиме ядра. При этом процессором выполняются системные инструкции ядра операционной системы от имени процесса.
  • 3 . Процесс не выполняется, но готов к запуску, как только планировщик выберет его (состояние runnable).Процесс находится в очереди на выполнение и обладает всеми необходимыми ему ресурсами, кроме вычислительных.
  • 4. Процесс находится в состоянии сна (asleep), ожидая недоступного в данный момент ресурса, например завершения операции ввода/вывода.
  • 5. Процесс возвращается из режима ядра в режим задачи, но ядро прерывает его и производит переключение контекста для запуска более высокоприоритетного процесса.
  • 6. Процесс только что создан вызовом fork и находится в переходном состоянии: он существует, но не готов к запуску и не находится в состоянии сна.
  • 7. Процесс выполнил системный вызов exit и перешел в состояние зомби (zombie, defunct). Как такового процесса не существует, но остаются записи, содержащие код возврата и временную статистику его выполнения, доступную для родительского процесса. Это состояние является конечным в жизненном цикле процесса.
Необходимо отметить, что не все процессы проходят через все множество состояний, приведенных выше.Процесс начинает свой жизненный путь с состояния 6 , когда родительский процесс выполняет системный вызов fork() . После того как создание процесса полностью завершено, процесс завершает "дочернюю часть" вызова и переходит в состояние 3 готовности к запуску, ожидая своей
очереди на выполнение. Когда планировщик выбирает процесс для выполнения, он переходит в состояние 1 и выполняется в режиме задачи. Выполнение в режиме задачи завершается в результате системного вызова или прерывания, и процесс переходит режим ядра, в котором выполняется код системного вызова или прерывания. После этого процесс опять может вернуться в режим задачи. Однако во время выполнения системного вызова в режиме ядра процессу может понадобиться недоступный в данный момент ресурс. Для ожидания доступа к такому ресурсу, процесс вызывает функцию ядра sleep() и переходит в состояние сна 4 . При этом процесс добровольно освобождает вычислительные ресурсы, которые предоставляются следующему наиболее приоритетному процессу. Когда ресурс становится доступным, ядро "пробуждает процесс", используя функцию wakeup() помещает его в очередь на выполнение, и процесс переходит в состояние "готов к запуску" 3 .
При предоставлении процессу вычислительных ресурсов происходит переключение контекста (context switch), в результате которого сохраняется образ, или контекст, текущего процесса, и управление передается новому. Переключение контекста может произойти, например, если процесс перешел в состояние сна, или если в состоянии готовности к запуску находится процесс с более высоким приоритетом, чем текущий. В последнем случае ядро не может немедленно прервать текущий процесс и произвести переключение контекста. Дело в том, что переключению контекста при выполнении в режиме ядра может привести к нарушению целостности самой системы.
Поэтому переключение контекста откладывается до момента перехода процесса из режима ядра в режим задачи, когда все системные операции завершены, и структуры данных ядра находятся в нормальном состоянии.
Таким образом, после того как планировщик выбрал процесс на запуск, последний начинает свое
выполнение в режиме ядра, где завершает переключение контекста. Дальнейшее состояние
процесса зависит от его предыстории: если процесс был только что создан или был прерван, возвращаясь в режим задачи, он немедленно переходит в этот режим. Если процесс начинает выполнение после состояния сна, он продолжает выполняться в режиме ядра, завершая системный вызов. Заметим, что такой процесс может быть прерван после завершения системного вызова в момент перехода из режима ядра в режим задачи, если в очереди существует более высокоприоритетный процесс. В UNIX 4xBSD определены дополнительные состояния процесса, в первую очередь связанные с системой управления заданиями и взаимодействием процесса с терминалом. Процесс может быть переведен в состояние "остановлен" с помощью сигналов останова SIGSTOP , SIGTTIN или SIGTTOU . В отличие от других сигналов, которые обрабатываются только для выполняющегося процесса, отправление этих сигналов приводит к немедленному изменению состояния В этом случае, если процесс выполняется или находится в очереди на запуск, его состояние изменяется на "остановлен". Если же процесс находился в состоянии сна, его состояние изменится на "остановлен в состоянии сна". Выход из этих состояний осуществляется сигналом продолжения SIGCONT , при этом из состояния "остановлен" процесс переходит в состояние "готов к запуску", а для процесса, остановленного в состоянии сна, следующим пунктом назначения является продолжение "сна".
Описанные возможности полностью реализованы и в SVR4.

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

Наконец, процесс выполняет системный вызов exit() и заканчивает свое выполнение. Процесс может быть также завершен вследствие получения сигнала. В обоих случаях ядро освобождаетресурсы,принадлежавшие процессу, за исключением кода возврата и статистики его выполнения, и переводит процесс в состояние "зомби". В этом состоянии процесс находится до тех пор, пока родительский процесс не выполнит один из системных вызовов после чего вся информация о процессе будет уничтожена, а родитель получит код возврата завершившегося процесса.

Принципы управления памятью

Маршал Кирк МакКузик FreeBSD - Архитектура и реализация <<-----------PDF ст.166

Управление памятью часть-1

12:51 - Разрешение адресов 34:21 - Оверлейная,динамическая структуры

59:26 - Линейное непрерывное отображение - Кусочно линейное (ст.25)


Управление памятью часть-2

Что было в начале? ООП или виртуальная память.

51:44--> "Виртуальная память"; <-(стр. 18)-> 56:03--> "Сегменты";


Буфер ассоциативной трансляции, Translation lookaside buffer (TLB) - это специализированный кэш центрального процессора, используемый для ускорения трансляции адреса виртуальной памяти в адрес физической памяти.
https://ru.wikipedia.org
https://www.ibm.com/support/knowledgecenter/.performance/cache_tlbs.htm

Одной из основных функций операционной системы является эффективное управление памятью.
Оперативная память, или основная память, или память с произвольным доступом (Random Access Memory, RAM). Время доступа к оперативной памяти составляет всего несколько циклов процессора, поэтому работа с данными, находящимся в памяти, обеспечивает максимальную производительность.
Данный ресурс, как правило, ограничен. В большей степени это справедливо для многозадачной операционной системы общего назначения, каковой является UNIX.
Поэтому данные, которые не могут быть размещены в оперативной памяти, располагаются на вторичных устройствах хранения, или во вторичной памяти, роль которой обычно выполняют
дисковые накопители. Время доступа ко вторичной памяти на несколько порядков превышает время доступа к оперативной памяти и требует активного содействия операционной системы.
Подсистема управления памятью UNIX отвечает за справедливое и эффективное распределение
разделяемого ресурса оперативной памяти между процессами и за обмен данными между оперативной и вторичной памятью. Часть операций производится аппаратно, устройством
управления памятью (Memory Management Unit, MMU) процессора под управлением операционной системы, чем достигается требуемое быстродействие.
Примитивное управление памятью значительно уменьшает функциональность операционной системы. Такие системы, как правило, позволяют загрузить в заранее определенное место в оперативной памяти единственную задачу и передать ей управление. При этом задача получает в свое
распоряжение все ресурсы компьютера (разделяя их, разумеется, с операционной системой),
а адреса, используемые задачей, являются физическими адресами оперативной памяти.
По скольку такой способ запуска и выполнения одной программы безусловно является наиболее быстрым он часто используется в специализированных микропроцессорных системах, однако практически неприменим в операционных системах общего назначения, какой является UNIX.
Можно сформулировать ряд возможностей, которые должна обеспечивать подсистема управления памятью современной многозадачной операционной системы:

  • Выполнение задач, размер которых превышает размер оперативной памяти.
  • Выполнение частично загруженных в память задач для минимизации времени их запуска.
  • Размещение нескольких задач в памяти одновременно для повышения эффективности использования процессора.
  • Размещение задачи в произвольном месте оперативной памяти.
  • Размещение задачи в нескольких различных частях оперативной памяти.
  • Совместное использование несколькими задачами одних и тех же областей памяти. Например, несколько процессов, выполняющих одну и ту же программу, могут совместно использовать сегмент кода.
  • возможность создания машинно-независимых кодов, то есть априори между программой и физической памятью не должно быть связи.
Все эти возможности реализованы в современных версиях UNIX с помощью виртуальной памяти , от эффективности реализации и работы этой подсистемы во многом зависит производительность многозадачной операционной системы в целом. Она позволяет дать приложению иллюзию доступности большого объема памяти, в то время как реально компьютер может обладать лишь небольшим объемом оперативной памяти. Это требует определения абстракции "адресного пространства", отличного от физического местонахождения памяти. Программа создает ссылки на коды и данные в своем адресном пространстве, такие адреса должны преобразовываться в адреса ячеек оперативной памяти. Передача информации в основную память для использования ее программой и выполнение трансляции адресов при каждом доступе к памяти вынуждает к совместным действиям как программную, так и аппаратную часть компьютера.
PS : LINUX

И того, процесс работает с виртуальными адресами, а не с физическими.

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

Linux поддерживает 3 уровня таблиц: каталог таблиц первого уровня (PGD - Page Table Directory),

каталог таблиц второго уровня (PMD - Medium Page Table Diractory), и, наконец, таблица дескрипторов (PTE - Page Table Entry). Реально конкретным процессором могут поддерживаться не все уровни, но запас позволяет поддерживать больше возможных архитектур (Intel имеет 2 уровня таблиц, а Alpha - целых 3).

Преобразование виртуального адреса в физический происходит соответственно в 3 этапа. Берется указатель PGD , имеющийся в структуре описывающий каждый процесс, преобразуется в указатель записи PMD , а последний преобразуется в указатель в таблице дескрипторов PTE . И, наконец, к реальному адресу, указывающему на начало страницы прибавляют смещение от ее начала. Хороший пример подобной процедуры можно посмотреть в функции ядра < partial_clear>.


Виртуальная и физическая память

Оперативная память является, одним из важных компонентов компьютерной системы. Ранние системы UNIX имели в своем распоряжении 64 Кбайт оперативной памяти, и это количество было явно недостаточным, современные компьютеры обладают гигабайтами оперативной памяти, и это все равно мало.
Оперативная память может быть представлена в виде последовательности байтов, каждый из которых имеет свой уникальный адрес, называемый физическим адресом. Именно эти адреса в конечном счете использует процессор, обмениваясь данными с оперативной памятью. Однако адресное пространство процесса существенным образом отличается от адресного пространства физической оперативной памяти. Представим себе, что адресное пространство процесса непосредственно отображалось бы в оперативную память, другими словами, что адреса, используемые процессом, являлись бы физическими адресами. При таком подходе на пути создания многозадачной системы нас ожидал бы ряд непреодолимых препятствий:
  • Во-первых, трудно себе представить механизм, защищающий адресное пространство одного процесса, от адресного пространства другого или, что более важно, от адресного пространства самой операционной системы. Поскольку каждый процесс работает с физическими адресами, нет никакой гарантии, что процесс не обратится к ячейкам памяти, принадлежащим другим процессам или ядру системы. Последствия такого обращения скорее всего будут весьма плачевными.
  • Во-вторых, уже на этапе компиляции необходимо было бы предусмотреть распределение существующего физического адресного пространства. При запуске каждый процесс должен занимать непрерывную и непересекающуюся область физических адресов.
  • В-третьих, подобное распределение памяти между процессами вряд ли можно назвать оптимальным. Объем физической оперативной памяти будет существенным образом ограничивать число процессов, одновременно выполняющихся в системе. Так восемь процессов, каждый из которых занимает 1 Мбайт памяти, исчерпают 8 Мбайт оперативной памяти, а операционная система при средней загрузке насчитывает более 80 процессов!
Все перечисленные проблемы преодолимы с помощью виртуальной памяти.
При этом адреса, используемые приложениями и самим ядром, не обязаны соответствовать физическим адресам. Виртуальные адреса транслируются или отображаются в физические на аппаратном уровне при активном участии ядра операционной системы. Смысл виртуальной памяти заключается в том, что каждый процесс выполняется в собственном виртуальном адресном пространстве .

Виртуальное адресное пространство - рай для процесса.

  • Во-первых, у процесса создается ощущение исключительности - ведь все адресное пространство принадлежит только ему.
  • Во-вторых, он больше не ограничен объемом физической памяти - виртуальная память может значительно превышать физическую. В результате процессы становятся изолированными друг от друга и не имеют возможности (даже при желании) "хозяйничать" в адресном пространстве соседа. Физическая память распределяется максимально эффективно - она не зависит от распределения виртуальной памяти отдельного процесса.
Очевидно, что для реализации виртуальной памяти необходим управляемый механизм отображения
виртуального адреса в физический. В современных компьютерных системах процесс отображения выполняется на аппаратном уровне (с помощью MMU )(бит MMU (бит "используемости")) обеспечивая высокую скорость трансляции.
Операционная система осуществляет управление этим процессом.

Современные процессоры, как правило, поддерживают объединение адресного пространства (сегментно - страничная организация памяти):

в области переменного размера - сегменты и

в области фиксированного размера - страницы,

понятие "страница" можно трактовать как способ организации памяти когда физическая память разделяется на блоки фиксированного размера (512-2Кб, кратное 2-ум), как и понятие "сегмент", "страница" одно из фундаметальных абстракций в понимании архитектуры и работы операционных систем. При этом для каждого сегмента или страницы может быть задано собственное отображение виртуальных адресов в физические.
Виртуальное адресное пространство процесса, как правило, является последовательно структуированным в рамках сегментов - кода, данных, стека и библиотек. Расположение соответствующих областей физической памяти может иметь фрагментированный характер. Размер виртуальной памяти может существенно превышать размер физической за счет использования вторичной памяти или области свопинга - как правило, дискового пространства, где могут сохраняться временно не используемые участки адресного пространства процесса. Например, если при выполнении процесса происходит обращение к виртуальному адресу, для которого присутствует соответствующая страница физической памяти, операция чтения или записи завершится успешно. Если страница в оперативной памяти отсутствует, процессор генерирует аппаратное прерывание, называемое страничной ошибкой (page fault) , в ответ на которое ядро определяет положение сохраненного содержимого страницы в области свопинга, считывает страницу в память, устанавливает параметры отображения виртуальных адресов в физические и сообщает процессору о необходимости повторить операцию. Все эти действия невидимы для приложения, которое работает с виртуальной памятью.
Механизм отображения виртуальных адресов в физические (трансляция адреса) существенным

образом зависит от конкретной аппаратной реализации. В этом разделе рассмотривается механизм отображения виртуальных адресов в физические в операционной системе SCO UNIX на примере семейства процессоров Intel. Однако, как и для остальных подсистем UNIX, основные принципы отличаются мало, и данное изложение поможет представить механизмы управления памятью и разобраться, при необходимости, в конкретной реализации.

Сегменты

Семейство процессоров Intel позволяет разделить память на несколько логических частей, называемых сегментами. При этом адресное пространство процесса может быть представлено в виде нескольких логических сегментов, каждый из которых состоит из непрерывной последовательности адресов, лежащих в заданном диапазоне. Трансляция адресов, основанная на сегментации,
предусматривает однозначное отображение адресов сегмента в непрерывную последовательность
физических адресов. Виртуальный адрес при этом состоит из двух частей: селектора сегмента и
смещения относительно начала сегмента. Селектор (точнее, поле селектора INDEX ) указывает на
так называемый дескриптор сегмента, содержащий такие параметры, как его расположение в памяти,
размер и права доступа. Процессор поддерживает косвенную адресацию сегментов через дескрипторы сегментов, которые располагаются в специальных таблицах - областях памяти, на которые указывают
предназначенные для этого регистры процессора. Ядро операционной системы отвечает за заполнение этих таблиц и установку значений регистров. Другими словами, ядро задает отображение, а процессор выполняет отображение на аппаратном уровне. Благодаря такой косвенной адресации логические сегменты защищены друг от друга, что обеспечивает целостность адресного пространства процесса и ядра.
Дескрипторы сегментов расположены в двух системных таблицах - локальной таблице дескрипторов
(Local Descriptor Table - LDT ) и глобальной таблице дескрипторов (Global Descriptor Table - GDT ).
Как следует из названия, LDT обеспечивает трансляцию виртуальных адресов сегментов процесса,
в то время как GDT обслуживает адресное пространство ядра (например, при обработке системного
вызова или прерывания).Для каждого процесса создается собственная LDT, в то время как GDT
разделяется всеми процессами. Информация о таблице, на которую указывает селектор, находится в самом селекторе.

1 5 3 2 1 0

INDEX TI RPL
Селектор сегмента
  • Поле INDEX является номером (индексом) дескриптора в таблице дескрипторов, который должен использоваться при вычислении линейного адреса.
  • Бит TI указывает, какая таблица дескрипторов должна использоваться Ø - соответствует GDT 1 - соответствует LDT
  • Поле RPL используется для контроля прав доступа программы к сегменту . является запрошенным уровнем привилегий и является одним из механизмов обеспечения защиты сегментов. Например, если процесс, находясь в режиме задачи, попытается обратиться к сегменту, принадлежащему ядру, процессор сгенерирует особую ситуацию, в ответ на это ядро отправит процессу сигнал SIGSEGV.
Каждая запись LDT или GDT является дескриптором сегмента. Определено несколько типов дескрипторов, используемых для сегментов кода, данных и стека, а также ряд дескрипторов,
с помощью которых обеспечивается многозадачность и передача управления от непривилегированной задачи, например, процесса в режиме задачи, к привилегированной задаче, например, ядру.
Дескрипторы, используемые в последнем случае, называются шлюзами.

Дескрипторы сегментов (кода, данных, стека) имеют несколько полей:

  • Базовый адрес В этом поле хранится 32-битный адрес начала сегмента. Процессор добавляет к нему смещение и получает 32-битный линейный адрес.
  • Предел Это поле определяет размер сегмента. Если результирующий линейный адрес выходит за пределы сегмента, процессор генерирует особую ситуацию. Границы сегмента позволяют процессору обнаруживать такие распространенные ошибки, как переполнение стека, неверные указатели, неверные адреса вызовов и переходов. В случае, когда операционная система считает, что обращение за пределы сегмента не является ошибкой (например, при переполнении стека), она может расширить сегмент путем выделения дополнительной памяти и запросить выполнение команды вновь.
  • Привилегии Это поле, имеющее название Descriptor Privilege Level (DPL), определяет уровень привилегий сегмента и используется совместно с полем RPL селектора для разрешения или запрещения доступа к сегменту. Для получения доступа к сегменту задача должна иметь по крайней мере такой же уровень привилегий, как и сегмент, т. е. RPL DPL.
  • Признак присутствия. Этот бит обеспечивает один из механизмов реализации виртуальной памяти. Если бит не установлен, при попытке обращения к сегменту процессор генерирует особую ситуацию отсутствия сегмента, позволяя ядру подгрузить сегмент из вторичной памяти и вновь повторить инструкцию, не затрагивая при этом выполнение процесса. Однако в большинстве современных версий UNIX виртуальная память основана на страничном механизме, при котором сегмент всегда присутствует в памяти, а обмен между оперативной и вторичной памятью происходит на уровне страниц.
  • Тип Это поле определяет тип сегмента. Процессор проверяет тип сегмента на соответствие исполняемой команде. Это, в частности, не позволяет интерпретировать информацию сегмента данных как инструкции процессора.
  • Права доступа Это поле определяет права доступа, ограничивающие множество операций, которые можно производить с сегментом. Например, сегмент кода обычно отмечается как исполняемый и читаемый. Сегменты данных могут иметь право доступа только для чтения, или для чтения и записи.
Комбинация селектора и смещения образует логический адрес. Блок управления памятью процессора
использует селектор для определения соответствующего ему дескриптора. Складывая базовый адрес сегмента, хранящийся в дескрипторе, со смещением, процессор создает линейный адрес. Если страничный механизм не используется, полученный линейный адрес является физическим, используемым для непосредственного доступа к оперативной памяти. Однако реализация виртуальной памяти, основанная только на сегментах, не обладает достаточной гибкостью и не используется в современных версиях. Управление памятью в большинстве систем основано на страничном механизме. Сегменты используются ядром для размещения кода, данных и стека процесса, причем каждый из них имеет нулевой базовый адрес и предел - 3 Гбайт, т. е. всю адресуемую виртуальную память за вычетом 1 Гбайт, занимаемых ядром системы.
Распределение виртуального адресного пространства между ядром и процессами рассмотрено в " ".

Страничный механизм

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

Страничный механизм обеспечивает гораздо большую гибкость. В этом случае все виртуальное адресное пространство (4 Гбайт для процессоров Intel) разделено на блоки одинакового размера, называемые страницами. Большинство процессоров Intel работает со страницами размером 4 Кбайт. Так же как и в случае сегментации, страница может либо присутствовать в оперативной памяти,
либо находиться в области свопинга или исполняемом файле процесса. Основное преимущество такой схемы заключается в том, что система управления памятью оперирует областями достаточно малого
размера для обеспечения эффективного распределения ресурсов памяти между процессами.
Страничный механизм допускает, чтобы часть сегмента находилась в оперативной памяти, а часть отсутствовала. Это дает ядру возможность разместить в памяти только те страницы, которые в данное время используются процессом, тем самым значительно освобождая оперативную память. Еще одним преимуществом является то, что страницы сегмента могут располагаться в физической памяти в произвольном месте и порядке,что позволяет эффективно использовать свободное пространство.
Данный подход напоминает схему хранения файлов на диске - каждый файл состоит из
различного числа блоков хранения данных, которые могут располагаться в любых свободных участках дискового накопителя. Это ведет к значительной фрагментации, но существенно повышает эффективность использования дискового пространства.

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


Page Directory Entry, PDE - Первое поле адреса, с 22 по 31 бит, указывает на элемент каталога таблиц страниц PDE . Каталог таблиц страниц имеет длину,равную одной странице, и содержит до 1024 указателей на таблицы страниц (page table). Таким образом, первое поле адресует определенную таблицу страниц.
Page Table Entry, РТЕ - Второе поле, занимающее с 12 по 21 бит, указывает на элемент таблицы страниц РТЕ . Таблицы страниц также имеют длину 4 Кбайт, а элементы таблицы адресуют в совокупности 1024 страниц. Другими словами, второе поле адресует определенную страницу.
Наконец, смещение на странице определяется третьим полем, занимающим младшие 12 бит линейного адреса. Таким образом, с помощью одного каталога таблиц процесс может адресовать

1024 x 1024 x 4096 = 4 Гбайт физической памяти.

На рис.выше показано, как блок страничной адресации процессора транслирует линейный адрес в физический. Процессор использует поле PDE адреса (старшие 10 бит) в качестве индекса в каталоге таблиц. Найденный элемент содержит адрес таблицы страниц. Второе поле линейного адреса РТЕ, позволяет процессору выбрать нужный элемент таблицы, адресующий физическую страницу. Складывая адрес начала страницы со смещением, хранящимся в третьем поле, процессор получает 32-битный физический адрес.

Большинство современных и, в частности, процессоры семейства Intel, помещают данные о нескольких последних использовавшихся ими страницах в сверхоперативный кэш. Только когда процессор не находит требуемой страницы в этом кэше, он обращается к каталогу и таблицам страниц. Как правило 99-98% адресных ссылок попадают в кэш, не требуя для трансляции адреса обращения к оперативной памяти, где расположены каталог и таблицы.
Каждый элемент таблицы страниц содержит несколько полей,описывающих различные

характеристики страницы. Поля PTE :


P
Признак присутствия в оперативной памяти. Доступ к странице, отсутствующей в памяти (Р=0) вызывает страничную ошибку, особую ситуацию,о чем процессор информирует ядро, которое обрабатывает ее соответствующим образом.
R/W Права только на чтение страницы (R/W=0)или на чтение и запись (R/W=1)

U/S
Привилегии доступа. Если U/S=0, только привилегированные задачи (ядро) имеют доступ к адресам страницы. В противном случае, доступ к странице имеют все задачи.
Адрес Физический адрес начала страницы (адрес базы)

Адресное пространство процесса

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

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

    создание процессов и потоков;

    обеспечение процессов и потоков необходимыми ресурсами;

    изоляция процессов ;

    планирование выполнения процессов и потоков (вообще, следует говорить и о планировании заданий);

    диспетчеризация потоков;

    организация межпроцессного взаимодействия;

    синхронизация процессов и потоков;

    завершение и уничтожение процессов и потоков.

1. К созданию процесса приводят пять основных событий:

    выполнение запроса работающего процесса на создание процесса;

    запрос пользователя на создание процесса, например, при входе в систему в интерактивном режиме;

    инициирование пакетного задания;

    создание операционной системой процесса, необходимого для работы каких-либо служб.

Обычно при загрузке ОС создаются несколько процессов. Некоторые из них являются высокоприоритетными процессами, обеспечивающими взаимодействие с пользователями и выполняющими заданную работу. Остальные процессы являются фоновыми, они не связаны с конкретными пользователями, но выполняют особые функции – например, связанные с электронной почтой, Web-страницами, выводом на печать , передачей файлов по сети, периодическим запуском программ (например,дефрагментации дисков ) и т.д. Фоновые процессы называют демонами.

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

2. С технической точки зрения во всех перечисленных случаях новый процесс формируется одинаково: текущий процесс выполняет системный запрос на создание нового процесса. Подсистема управления процессами и потоками отвечает за обеспечение процессов необходимыми ресурсами . ОС поддерживает в памяти специальные информационные структуры, в которые записывает, какие ресурсы выделены каждому процессу. Она может назначить процессу ресурсы в единоличное пользование или совместное пользование с другими процессами. Некоторые из ресурсов выделяются процессу при его создании, а некоторые – динамическипо запросам во время выполнения . Ресурсы могут быть выделены процессу на все время его жизни или только на определенный период. При выполнении этих функций подсистема управления процессами взаимодействует с другими подсистемами ОС, ответственными за управление ресурсами , такими как подсистема управления памятью, подсистема ввода-вывода , файловая система .

3. Для того чтобы процессы не могли вмешаться в распределение ресурсов , а также не могли повредить коды и данные друг друга, важнейшей задачей ОС является изоляция одного процесса от другого . Для этого операционная система обеспечивает каждый процесс отдельным виртуальным адресным пространством, так что ни один процесс не может получить прямого доступа к командам и данным другого процесса.

4. В ОС, где существуют процессы и потоки, процесс рассматривается как заявка на потребление всех видов ресурсов, кроме одного – процессорного времени. Этот важнейший ресурс распределяется операционной системой между другими единицами работы – потоками, которые и получили свое название благодаря тому, что они представляют собой последовательности (потоки выполнения) команд. Переход от выполнения одного потока к другому осуществляется в результате планирования и диспетчеризации . Работа по определению момента, в который необходимо прервать выполнение текущего потока, и потока, которому следует предоставить возможность выполняться, называется планированием. Планирование потоков осуществляется на основе информации, хранящейся в описателях процессов и потоков. При планировании принимается во внимание приоритет потоков , время их ожидания в очереди, накопленное время выполнения , интенсивность обращения к вводу-выводу и другие факторы.

5. Диспетчеризация заключается в реализации найденного в результате планирования решения, т.е. в переключении процессора с одного потока на другой. Диспетчеризация проходит в три этапа:

    сохранение контекста текущего потока;

    запуск нового потока на выполнение.

6. Когда в системе одновременно выполняется несколько независимых задач, возникают дополнительные проблемы. Хотя потоки возникают и выполняются синхронно, у них может возникнуть необходимость во взаимодействии , например, при обмене данными. Для общения друг с другом процессы и потоки могут использовать широкий спектр возможностей: каналы (в UNIX ), почтовые ящики (Windows ), вызов удаленной процедуры, сокеты (в Windows соединяют процессы на разных машинах). Согласование скоростей потоков также очень важно для предотвращения эффекта "гонок" (когда несколько потоков пытаются изменить один и тот же файл ), взаимных блокировок и других коллизий, которые возникают при совместном использовании ресурсов.

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

8. Каждый раз, когда процесс завершается , – а это происходит благодаря одному из следующих событий: обычный выход , выход по ошибке, выход по неисправимой ошибке, уничтожение другим процессом – ОС предпринимает шаги, чтобы "зачистить следы" его пребывания в системе. Подсистема управления процессами закрывает все файлы, с которыми работал процесс, освобождает области оперативной памяти, отведенные под коды, данные и системные информационные структуры процесса. Выполняется коррекция всевозможных очередей ОС и список ресурсов, в которых имелись ссылки на завершаемый процесс.

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

  • выполнение запроса работающего процесса на создание процесса;
  • запрос пользователя на создание процесса, например, при входе в систему в интерактивном режиме;
  • инициирование пакетного задания;
  • создание операционной системой процесса, необходимого для работы каких-либо служб.
  • Обычно при загрузке ОС создаются несколько процессов. Некоторые из них являются высокоприоритетными процессами, обеспечивающими взаимодействие с пользователями и выполняющими заданную работу. Остальные процессы являются фоновыми, они не связаны с конкретными пользователями, но выполняют особые функции – например, связанные с электронной почтой, Web-страницами, выводом на печать , передачей файлов по сети, периодическим запуском программ (например, дефрагментации дисков ) и т.д. Фоновые процессы называют демонами.

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

    С технической точки зрения во всех перечисленных случаях новый процесс формируется одинаково: текущий процесс выполняет системный запрос на создание нового процесса. Подсистема управления процессами и потоками отвечает за обеспечение процессов необходимыми ресурсами. ОС поддерживает в памяти специальные информационные структуры, в которые записывает, какие ресурсы выделены каждому процессу. Она может назначить процессу ресурсы в единоличное пользование или совместное пользование с другими процессами. Некоторые из ресурсов выделяются процессу при его создании, а некоторые – динамически по запросам во время выполнения . Ресурсы могут быть выделены процессу на все время его жизни или только на определенный период. При выполнении этих функций подсистема управления процессами взаимодействует с другими подсистемами ОС, ответственными за управление ресурсами , такими как подсистема управления памятью, подсистема ввода-вывода , файловая система .

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

    В ОС, где существуют процессы и потоки, процесс рассматривается как заявка на потребление всех видов ресурсов, кроме одного – процессорного времени. Этот важнейший ресурс распределяется операционной системой между другими единицами работы – потоками, которые и получили свое название благодаря тому, что они представляют собой последовательности (потоки выполнения) команд. Переход от выполнения одного потока к другому осуществляется в результате планирования и диспетчеризации . Работа по определению момента, в который необходимо прервать выполнение текущего потока, и потока, которому следует предоставить возможность выполняться, называется планированием. Планирование потоков осуществляется на основе информации, хранящейся в описателях процессов и потоков. При планировании принимается во внимание приоритет потоков , время их ожидания в очереди, накопленное время выполнения , интенсивность обращения к вводу-выводу и другие факторы.

    Диспетчеризация заключается в реализации найденного в результате планирования решения, т.е. в переключении процессора с одного потока на другой. Диспетчеризация проходит в три этапа:

    • сохранение контекста текущего потока;
    • загрузка контекста потока, выбранного в результате планирования;
    • запуск нового потока на выполнение.

    Когда в системе одновременно выполняется несколько независимых задач, возникают дополнительные проблемы. Хотя потоки возникают и выполняются синхронно, у них может возникнуть необходимость во взаимодействии, например, при обмене данными. Для общения друг с другом процессы и потоки могут использовать широкий спектр возможностей: каналы (в UNIX ), почтовые ящики ( Windows ), вызов удаленной процедуры, сокеты (в Windows соединяют процессы на разных машинах). Согласование скоростей потоков также очень важно для предотвращения эффекта "гонок" (когда несколько потоков пытаются изменить один и тот же файл ), взаимных блокировок и других коллизий, которые возникают при совместном использовании ресурсов.

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

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

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

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

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

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

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

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

    Другим решением является создание для одного приложения нескольких процессов для каждой из параллельных