Найти тему
Разумный мир

Многозадачная Операционная Система. Как это работает

Оглавление

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

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

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

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

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

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

Что такое машина

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

Наша машина будет устроена вот так

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

Как видно, это совершенно типовая простая ЭВМ содержащая минимальный набор компонентов. Процессор выполняет программный код, который хранится в оперативной памяти (ОЗУ - оперативное запоминающее устройство). Так же в ОЗУ хранятся и данные, которые обрабатывает программа.

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

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

Структура распределения оперативной памяти нашей машины. Иллюстрация моя
Структура распределения оперативной памяти нашей машины. Иллюстрация моя

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

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

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

Но самая важная для нас сегодня область ОЗУ это область, в которой и располагаются программы и данные пользователя. Эта область ограничена начальным и конечным адресами. И размер этой области меньше размера физически установленной в машине памяти.

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

Что такое задача

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

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

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

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

Однозадачная ОС

Когда то давно, когда ЭВМ были большими, дорогими, но умели немногое, ОС еще не существовало. Но в эти, почти былинные, времена мы погружаться не будем. Первые ОС были скорее "программами-мониторами", которые возможно еще помнят те, кто в 80-90-е годы прошлого века пользовался первыми бытовыми ЭВМ. А возможно и сам собирал такие.

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

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

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

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

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

И с этим нужно было что то делать. И первым получившим распространение способом повышения эффективности использования ЭВМ стало разделение задач на фоновые и переднего плана.

ОС с возможностью выполнения фоновых задач

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

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

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

Теперь в ОЗУ одновременно размещаются две задачи. И это приводит к появлению первой проблемы. Дело в том, что большинство задач рассчитаны на то, что они располагаются в памяти начиная с определенного адреса. Мы не можем загрузить задачу в другую область памяти, она просто перестанет работать.

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

Поэтому на первых порах поступили просто - разделили всю доступную для программ пользователей память на две области

Разделение области прикладных программ на две независимые части - область задач переднего плана и область фоновых задач. Иллюстрация моя
Разделение области прикладных программ на две независимые части - область задач переднего плана и область фоновых задач. Иллюстрация моя

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

Может показаться, что такое разделение области памяти прикладных программ вносит дополнительные ограничения на размер задач. Для фоновых задач это действительно так. Фоновая задача не может использовать памяти задач переднего плана.

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

Возникает вопрос, как ОС узнает, что нужно передать управление фоновой задаче? Это возможно только в том случае, если задача переднего плана сама отдаст, на время, управление. И этого добиться довольно просто.

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

Фоновая задача выполняется во время пауз выполнения задачи переднего плана при ожидании завершения ввода-вывода. Иллюстрация моя
Фоновая задача выполняется во время пауз выполнения задачи переднего плана при ожидании завершения ввода-вывода. Иллюстрация моя

Теперь понятно, почему задачей переднего плана считается именно задача с большим объемом ввода-вывода. Именно такая задача будет давать возможность выполняться фоновой задаче. Если задача переднего плана займется вычислениями и не будет запрашивать ввод-вывод, фоновая задача просто не получит шансов на выполнение.

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

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

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

Сохранение состояния

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

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

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

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

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

Переключение задач требует сохранение и восстановление состояния процессора. Иллюстрация моя
Переключение задач требует сохранение и восстановление состояния процессора. Иллюстрация моя

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

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

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

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

Поэтому следующий шагом в развитии ОС стал совершенно естественным

Системы с разделением времени

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

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

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

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

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

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

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

Переключение задач разного приоритета в системе с разделением времени. Иллюстрация моя
Переключение задач разного приоритета в системе с разделением времени. Иллюстрация моя

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

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

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

И во втором приближении процесс переключения будет выглядеть так

Переключение задач одного приоритета, но без учета завершения ввода-вывода, в системе с разделением времени. Иллюстрация моя
Переключение задач одного приоритета, но без учета завершения ввода-вывода, в системе с разделением времени. Иллюстрация моя

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

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

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

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

Поэтому было введено понятие состояния задачи. Давайте кратко рассмотрим тот вопрос

Состояния задачи

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

  • Приостановленной. При этом выполняется другая задача
  • Выполняющейся.

Введение принудительного переключения задач по времени потребовало дополнительного состояния задачи - состояния ожидания. В состояние ожидания переводится задача после запроса ввода-вывода. И ОС не будет выделять задаче в состоянии ожидания кванты процессорного времени. Такая задача просто выпадает на время из процесса переключения задач.

После завершения ввода-вывода состояние задачи меняется с "ожидание" на " приостановлена". И задача снова начинает участвовать в процессе переключения.

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

Планировщик задач

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

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

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

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

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

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

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

Это очень упрощенный алгоритм работы простейшего варианта планировка задач. Но нам сегодня этого достаточно.

Итак, ключевым элементом является именно счетчик тиков. Его начальное значение устанавливается планировщиков с учетом приоритета задачи. Чем выше приоритет, тем большее значение получит счетчик при переключении на задачу.

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

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

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

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

Управление памятью и размещение задач в памяти

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

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

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

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

Диспетчер памяти, логические и физические адреса памяти

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

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

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

Пример работы диспетчера памяти. Иллюстрация моя
Пример работы диспетчера памяти. Иллюстрация моя

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

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

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

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

Это повышает накладные расходы в виде дополнительной памяти, занятой под таблицы преобразования адресов. И усложняет процессор. Но плюсы перевешивают. И такая страничная организация памяти сегодня довольно распространена. Причем и в виде гораздо более сложных вариантов. Когда то давно я написал статью об организации памяти в Intel 80х86

Адресация физической памяти в процессорах Intel 80х86 и совместимых

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

Разделяемый ресурс

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

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

Я проиллюстрирую это примерами из обычной жизни. Предположим, у нас есть лист бумаги. Несколько человек могут одновременно читать, что на нем написано. Но писать на этом листе может только один человек, иначе пишущие просто будут мешать друг другу. И во время письма написанное на листе полностью прочитано быть не может. Давно написанное читается, то что пишется в данный момент просто еще не закончено.

Лист бумаги при этом и будет тем самым разделяемым ресурсом. В мире ЭВМ такому листу может соответствовать, например, файл на диске или сетевом хранилище. А может и общая, разделяемая, область памяти.

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

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

Заключение

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

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

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

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

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

До новых встреч!