Методы реализации системного программирования
Системное программирование – это наука о представлении, реализации, свойствах и конструкции комплекса программ для ВС, который организует принятие и обработку запросов при определенных требованиях к оптимальности и выполняет эти запросы. Возможными требованиями к оптимальности являются:
· надежность,
· комфортность пользовательского интерфейса,
· время ответа,
· владение ситуацией при запросах,
· легкость модификаций,
· устойчивость (робастность)
К типичным задачам системного программирования относятся разработка ОС и реализация системных программ, не принадлежащих ОС. Сюда относятся программное обеспечение для коммуникаций, необходимых при построении сетей ЭВМ.
Общие функкции и грубая структура ОС были уже обсуждены в предыдущих разделах. Теперь мы обратится к ряду особо важных концепций, которые встречаются в современных ОС.
Концепция прерываний
Мультипрограммный режим работы ставит своей целью оптимальное использование и загрузку всех устройств ВС. Для достижения этой цели выполнение программы обычно разбивается на много отдельных частей. Это значит, что выполнение программы, как правило, многократно прерывается. Мы говорим о концепции прерываний. Для прерывания выполнения пользовательской программы существует много причин:
· программа использовала выделенное ей процессорное время;
· программа требует использования устройств или файлов, которых в данный момент нет в ее распоряжении;
· устройство ввода/вывода сигнализирует процессору, что оно заверши-то выполнение выданного ему заказа;
· оператор ЭВМ (или пользователь) принял решение приостановить выполнение программы;
· встретилась ошибка.
Если прерывание выполнения пользовательской программы вызвано каким-либо внешним событием, что мы говорим о вмешательстве (внешнее прерывание); в противном случае - о тревоге (внутреннее прерывание). В случае вмешательства фактическое выполнение программы прерывается, так как имеет место внешнее событие, на которое необходимо отреагировать, например сигнал от устройства ввода/вывода или команда оператора.
Наряду с указанными выше основаниями к прерыванию программы могут вести различные ошибочные случаи - например, тревога по защите памяти (недопустимая последовательность битов в адресной части команды), операционная тревога (в команде задан недопустимый код операции), машинная тревога (сбой аппаратуры) и многие другие.
Пример (процессор с концепцией прерываний). Схематично такт работы процессора с концепцией прерываний мог бы выглядеть следующим образом:
while true do
продвижение счетчика команд; вычисление абсолютного адреса команды; контроль по защите памяти (в случае необходимости тревога по защите памяти);
в случае возникновения прерывания - его обработка; вычисление абсолютных адресов операндов; контроль по защите памяти (в случае необходимости - тревога по защите памяти);
контроль за командой (в случае необходимости - операционная тревога).
В этом примере могут возникать как вмешательства, так и внутренние события (как ошибочные ситуации во время выполнения команды, например деление на нуль), которые влекут прерывание выполняемой сейчас программы. Возникновение вмешательства или тревоги ведет к прерыванию программы, выполняемой в данное время процессором. Конечно, выполнение программы или, точнее, такта работы не может прерываться в любом его месте, а только в таких местах, которые сделают возможным последующее продолжение выполнения прерванной программы. Поэтому при возникновении прерывания должна быть спасена вся та информация о состоянии программы (в том числе и содержимое относящихся к делу регистров), которая необходима для того, чтобы позднее можно было корректно продолжить выполнение данной программы.
Конкретное представление состояния процесса должно быть запомнено.
Совокупность содержимого этих регистров назовем состоянием процессора пользовательской программы, которое является составной частью контекста процесса. Спасение состояния процессора путем его запоминания, так же как и выполнение соответствующих управляющих действий (занесение прерванного заказа в предназначенную для этого очередь ожидания), образует первую часть обработки прерывания).
После запоминания состояния прерванной программы включается в работу программа ОС, которая в соответствии с причиной прерывания принимает необходимые организационные меры. Не исключено, что во время проведения этих мер возникнет новое вмешательство или тревога и тем самым возникнет необходимость нового прерывания. Однако нет особенного смысла и по меньшей мере опасно прерывать саму обработку прерывания, Поэтому введем концепцию блокировки прерывания. Технически это означает, например, что при выполнении программы ОС ^взводится» специальный триггер, вследствие чего вмешательство не вытечет за собой немедленного прерывания. В сложных ОС могут существовать иерархии различного рода блокировок прерываний, которые откладывают реакцию только на определенные вмешательства, а при друтих разрешают прерывания.
Установление блокировки прерываний, как и ряд других команд (установка некоторых регистров или часов и т. п.), должно быть привилегированной командой. Такие команды должны быть доступны для использования только системным программистам и операторам ЭВМ, но недоступны для обычных пользователей. Тем самым обеспечивается, что
обычный пользователь не может - нечаянно или умышленно - недозволенным образом воздействовать на поведение системы. Если бы пользователю было позволено, например, устанавливать блокировку прерываний, то он мог бы нежелательным образом, скажем, зарезервировать процессор исключительно для себя.
В ВС с концепцией прерываний различается тем самым два режима работы системы: нормальный режим (или режим пользователя), в котором выполняются пользовательские программы и системные программы в расширенном смысле (например, трансляторы); в этих программах не допускается использование привилегированных команд, и программы работают с виртуальными адресами (см.
следующий раздел);
системный режим(или привилегированный режим), в котором выполняются программы ОС; в этих программах могут беспрепятственно выполняться и привилегированные команды, и в них может использоваться адресация физических запоминающих устройств.
Мы делаем различие между системными режимами с блокировкой и без блокировки прерываний. Поясним концепцию прерываний. Возврат из системного вызова осуществляется командой REI (без признака; без адреса; “return from interrupt” - возврат из прерывания). Пользовательская программа доступна системе через стек, называемый системным стеком. Команда СНМК (без признака; “change modus to kernel” - установить режим системы) запоминает в системном стеке минимум информации, необходимой для последующего продолжения программы. Запоминаются следующие три значения в указанном здесь порядке:
· числовой признак (адрес) вызываемой системной службы;
· текущее значение счетчика команд;
· текущее значение регистра, в котором хранится слово состояния программы PSW (от англ. Programm State Word. - Пер.).
В заключение устанавливается в качестве рабочего режим системы и соответствующее PSW. В счетчик команд заносится начальный адрес запрошенной службы системы.
Состояние программы складывается из совокупности всех характеристических величин, которые общественны для выполнения программы. Обратим внимание, что мы можем восстановить содержимое всех имеющих отношение к выполнению программы регистров, вплоть до реального времени.
Состояние программы какого-либо процесса описывается через конкретизацию регистров процессора, если только программа фактически выполняется. Если выполнение программы прервано и она перестает быть активной, то состояние программы сохраняется в блоке управления процессом. Этот блок охватывает следующую информацию:
· указатель стека в режиме системы,
· указатель стека в режиме пользователя,
· содержимое регистров
· слово состояния процессора PSW,
· начальный адрес и длину ( число страниц) таблицы страниц области памяти для пользовательской программы,
· начальный адрес и длину таблицы страниц для стека пользователя.
Синхронизация
В мультипрограммных и мультипроцессорных системах часто бывает необходима синхронизация хода выполнения определенных участков программы. Такая синхронизация может быть осуществлена с помощью семафоров. Однако аппаратура часто предоставляет лишь примитивные механизмы синхронизации, на которые и должна опираться реализация семафоров. Для синхронизации имеется в распоряжении следующая команда: JBSSI (“jump on bit set and set interlocked”). Эта команда выполняется как неделимое целое, и поэтому ее выполнение не может быть прервано. Команда использует три операнда:
JBSSI а, Р, у.
С помощью этих операндов адресуется бит в массиве битов. При этом пусть Р, у - операнды-спецификации; a - относительный адрес (число бит) бита в байте, заданном адресом р. Выполнение команды JBSSI а, р, у влечет следующее изменение состояния:
· занесение в счетчик команд значения, специфицированного с помощью у.
· в этот бит заносится значение L.
Итак, эта команда в любом случае приводит к состоянию, в котором упомянутый бит имеет значение L. Если перед выполнением команды этот бит уже имел значение L, то в счетчик команд заносится соответствующее значение. Про такого рода команды говорят также как о “test and set^-командах (т. е. командах проверки и установки). Команда
JBCCI (“jump on bit cleard and clear interlocked)
действует аналогично команде JBSSI с той разницей, что в счетчик команд заносится значение у, если упомянутый бит имеет значение О и этот бит в любом случае получает значение О.
С помощью этих двух команд могут быть реализованы семафоры.
Другой классический пример примитивного механизма синхронизации на машинном уровне - это команды, которые за одно-единственное неделимое привилегированное действие обменивают содержимое определенных ячеек памяти и, соответственно, регистров. При этом в мультипроцессорных системах на уровне аппаратуры обеспечивается, что по мере необходимости в каждый момент времени только один процессор может производить такой обмен.
В ОС может, в частности, применяться концепция семафоров. Впрочем, тогда мы работаем, как правьте, с очередями ожидания и семафорные операции реализуются путем обращений к системам, которые выполняются при заблокированных прерываниях.
Реализация семафоров через описанные команды является типичным примером для системного программирования, при котором сочетается использование команд и вызовов служб системы.
Сегментация
Общее количество ячеек памяти (адресов), на которые пользователь может ссылаться в процессе выполнения своей программы, называют адресным пространством пользователя. Часто адресное пространство ЭВМ делится на определенные сегменты, в которые объединяются (по содержанию или организационно связанные друг с другом) ячейки памяти. Сегменты могут идентифицироваться обозначениями. Каждый сегмент обладает начальным адресом, каковым является адрес первой ячейки, входящей в этот сегмент, и тогда на ячейки памяти в сегментах ссылаются с помощью относительной адресации, используя начальный адрес сегмента. Длины сегментов (т. е. число входящих в них ячеек памяти) могут быть различны и даже динамически изменяться. Обратим внимание, что в оперативной памяти сегменты физически не обязательно должны быть представлены связно, и не обязательно все сегменты должны одновременно быть в оперативной памяти. В общем случае для многих ОС справедливы следующие высказывания:
· адресное пространство контекста процесса состоит из нескольких сегментов (число которых может изменяться);
· для каждой части программы и каждой области данных выделяется один сегмент (включая данные для регулирования права доступа и свойств);
· доступ к содержимое сегментов осуществляется с помощью пары (В, р), состоящей из обозначения сегмента В и относительного адреса р;
· части программы в своих сегментах организуются как подпрограммы.
С помощью техники сегментирования в ОС создается виртуальное адресное пространство. Программисту в этом случае не нужно думать и программировать учитывая технически (физически) заданную структуру памяти, а нужно лишь организовать свою программ в сегменты. Отображение виртуального адресного пространства на физическое осуществляет ОС.
Пример (реализация сегментирования). Сегментирование можно осуществить следующим образом. Для каждой секции программы заводится таблица сегментов. ОС управляет регистром таблицы сегментов, который содержит адреса таблиц сегментов отдельных секций. Таблица сегментов содержит (перенумерованные) сегменты пользовательской секции. Таким образом, адрес ячейки в сегменте состоит из номера таблицы, номера сегмента и относительного адреса.
Сегментирование имеет следующие важные преимущества:
· простоте структуру доступа к ячейкам для пользователя,
· наглядную) организацию прав доступа.
Разумеется, сегментирование не обостряет проблему ограниченности емкости памяти.
Метод страничного обмена
Несмотря на применение полупроводниковой памяти и больших интегральных схем для построения оперативной памяти, во многих ситуациях ее емкость оказывается все же недостаточной для одновременного размещения всех находящихся в машине программ и используемых в них данных. Поэтому непосредственно в оперативной памяти обычно держат лишь часть этой информации, а остальную размешают во внешней памяти.
Распространенная методика работы с памятью исходит из гораздо большей по емкости фиктивной, виртуальной оперативной памяти, чем фактически имеющаяся в распоряжении память. Эта виртуальная память делится на части одинакового размера (страницы, англ. pages), и в физической оперативной памяти держится только ограниченное число страниц. Если нужно обратиться для чтения или записи к странице, которой нет в оперативной памяти, то эта страница переносится из внешней памяти в оперативную. Для этого нужно предварительно какую-либо страницу из оперативной памяти перенести во внешнюю, чтобы освободить место в оперативной памяти. Здесь мы также говорим о виртуальной' памяти и специально о методе страничного обмена (англ. paging).
При этом методе физическая оперативная память делится на некоторое число кусков (изразцов), которые по мере необходимости могут принимать на хранение страницы виртуальной памяти. При этом виртуальное адресное пространство программы соответствует числу страниц. Физическая оперативная память и различного рода внешняя память соответствуют числу изразцов. Соответствие номеров страниц и номеров изразцов задается таблицей страниц (называемой также таблицей страница-изразец). Тогда виртуальный адрес состоит из номера страницы и номера ячейки в странице (относительного адреса в странице), а физический адрес в оперативной памяти - из номера изразца и номера ячейки в нем. Если желаемая страница находится не в оперативной памяти (в таблице страниц не содержится номера изразца), а во внешней, то она переносится в оперативного память и записывается в некоторый ее изразец. При этом в случае необходимости, чтобы освободить этот изразец, хранящаяся в .нем страница переносится во внешнюю память.
Важной составной частью метода страничного обмена является стратегия обмена страниц. Под этим понимается способ решения вопроса о том, когда и какая страница должна загружаться в оперативную память и, наоборот, переноситься во внешнюю память. Можно стараться держать в оперативной памяти почти все адресное пространство секции, или - другая крайность - только очень немного страниц из секции.
Если выбрать неудачную стратегию, то это может привести к «страничное флаттеру» - слишком частот обмену страницами. Тогда будет выполняться слишком много команд транспортирования. Темп обмена страницами будет столь высоким, что каналам и внешней памяти трудно будет работать согласованно и время выполнения программы будет слишком большим.
Метод страничного обмена для управления оперативной памятью имеет следующие преимущества:
· Благодаря делению памяти на части можно достичь гибкого предоставления и расширения предоставленной пользователю памяти без перезапоминания в оперативной памяти.
· Возникает большее (виртуальное) адресное пространство, чем имеющееся физически.
· Возможно перекрытие памяти. Благодаря этому поддерживается выполнимость секций, чьи программы и данные не полностью находятся в оперативной памяти.
· Общие отрезки памяти просто управляемы.
Метод страничного обмена служит для организации распределения такого ресурса, как оперативная память. Для организации адресного пространства отдельных секций служит сегментирование. Иногда используется комбинация сегментирования и страничного обмена, что показано на рис. 2.7.
Релокация программ
При мультипрограммном режиме выполняемая программа может многократно переноситься из внешней памяти в оперативного и наоборот. При этом было бы затруднительно требовать, чтобы она каждый раз занимала одно и то же абсолютное место в оперативной памяти. Следовательно, пользовательские программы должны быть оформлены так, чтобы они были перемещаемы в памяти. Поэтому обычно работают с относительно адресованными программами, которые помещаются в сегменты. Сегменты - это интервалы в виртуальной памяти, которые характеризуются начальными и конечными адресами. Описанная техника адресации может быть легко поддержана аппаратурой. С этой целью предусматривается два регистра для хранения начального и конечного адресов.
Эти регистры назовем регистром базы и регистр конца. При выполнении программы ее адресация ведется относительно содержимого регистра базы (динамическая фиксация), а с помощью регистра конца проверяется, используется ли допустимый адрес (защита памяти).
Загрузка регистров базы и конца осуществляется привилегированной командой, которая доступна только системе (в противном случае было бы невозможно обеспечить защиту памяти). В режиме системы зашить памяти должна, по крайней мере частично, исключаться, чтобы сделать доступной для системных программ необходимую им информацию (абсолютная адресация). Таким образом, существуют различные виды адресации.
Одновременное использование подпрограмм
Определенные программные части (хранимые в определенных сегментах) в мультипрограммном режиме используются во многих секциях. Было бы неэффективно и расточительно, если бы каждая секция обладала своей копией соответствующих кодов. Поэтому такие отрезки кодов помещают в специальные области памяти для совместного использования. Чтобы подпрограмма могла использоваться одновременно несколькими программами, требуется принять перечисленные ниже меры предосторожности. Эти меры могут быть поддержаны аппаратурой, например путем введения специального регистра (см. трансляционный регистр в [SEEGMULLER 761) или путем соблюдения соответствующей дисциплины программирования. Фрагмент программы, который в отношении адресных пространств гарантирует его корректное выполнение без каких-либо мер для взаимных исключений, называется реентерабельным (инвариантным к входу, с повторной входимостью, англ. reentrant). Технически это означает, что специфичные для программы адреса и данные управляются только через специальные организационные адреса, которые должны удовлетворять определенным условиям. Таким образом, при составлении реентерабельных программ необходимо обращать внимание на следующие требования:
· внутри сегмента, который содержит реентерабельную подпрограмму, нельзя что-либо запоминать;
· все ячейки памяти, содержимое которых изменяется при выполнении подпрограммы, управляются через передающий регистр и находятся в области памяти, предоставляемой вызывающей программой;
· защита памяти ограничена;
· загрузка передающего регистра является привилегированной командой;
· управление параметрами и вспомогательными ячейками должно производиться по определенным правилам
Вообще при оформлении программ рекомендуется обращать внимание на некоторые из оказанных выше пактов, так как благодаря этому повышается надежность и устойчивость (робастность) программ.
Управление устройствами ввода/вывода
Выделение устройств осуществляется ОС по запросам пользовательских программ на ввод/вывод. Данные с устройства ввода передаются в оперативную память с помощью канала, работающего по заказам ОС; вывод осуществляется аналогично, но в обратном направлении.
Внешняя память и устройства ввода/вывода работают по электромеханическим принципам и потому по сравнению с процессором и оперативной памятью, которые работают по чисто электронным принципам, имеют существенно меньшее быстродействие. Поэтому процессор и эти устройства работают асинхронно и связаны между собой с помощью каналов. Технически канал является достаточно простым, программно управляемым устройством, которое может выполнять простые канальные программы. Каждая такая программа состоит из последовательности команд, которые и управляют движением данных, протекающих через канал.
Как и процессор, каналы работают с памятью самостоятельно. Поэтов мы говорим, что в такой системе имеется много активных компонент или интерпретирующих устройств. Каналы могут приводиться в действие следующими двумя способами:
· через прерывание: каналы прерывают выполнение пользовательской программы, чтобы полнить от процессора новый заказ для себя (англ.interrupt);
· через повторяющиеся опросы: процессор периодически опрашивает каналы, чтобы узнать, можно ли выдать каналу новый заказ (англ. polling).
Различные возникающие в работе системы ситуации при мультипрограммном режиме снова могут быть описаны как изменение состояний системы.
Содержание раздела