- •Структура сети и коммутация пакетов.
- •Логическая и программная структура сети.
- •Iso(Intrnational Standarts Organization), мос(Межднародная Организация Стандартов).
- •Проектирование сетей эвм.
- •Задача выбора пропускных способностей.
- •Задача распределения потоков.
- •Задача выбора пропускных способностей и распределения потоков (впс и рп).
- •Выбор топологии сети.
- •Адресация, маршрутизация пакетов и управление потоками данных.
- •Протоколы и интерфейсы вычислительной сети.
- •Протокол hdlc (High Data Link Connection).
- •Транспортная сеть.
- •Протокол х.25/3.
- •Типы и форматы пакетов протокола х.25
- •Стек протоколов tcp/ip.
- •Формат ip-заголовка.
- •Сегменты тср.
- •Протокол udp ( user datagram protocol)
- •Коммутация пакетов при передаче данных через спутник.
- •Опорные точки.
- •Передача управляющих сигналов.
- •Основные методы доступа к среде.
- •Случайный доступ.
- •Локальная сеть Token Ring (ieee 802.5)
- •Форматы пакетов Token Ring.
- •Свойства объекта.
- •Допустимые права на файл.
- •Допустимые права на объект.
- •Опекунство.
- •Управление разделами и репликация.
- •Функции операционной системы.
- •Аппаратная среда.
- •Распределение памяти.
- •“Заблудшие" процессы
Распределение памяти.
Ядро постоянно располагается в оперативной памяти, наряду с выполняющимся в данный момент процессом. В процессе компиляции программа-компилятор генерирует последовательность адресов, являющихся адресами переменных и информационных структур, а также адресами инструкций и функций. Компилятор генерирует адреса для виртуальной машины так, словно на физической машине не будет выполняться параллельно с транслируемой ни одна другая программа.
Когда программа запускается на выполнение, ядро выделяет для нее место в оперативной памяти, при этом совпадение виртуальных адресов, сгенерированных компилятором, с физическими адресами совсем необязательно. Ядро, взаимодействуя с аппаратными средствами, транслирует виртуальные адреса в физические, т.е. отображает адреса, сгенерированные компилятором, в физические, машинные адреса. Такое отображение опирается на возможности аппаратных средств, поэтому компоненты системы UNIX, занимающиеся им, являются машинно-зависимыми. Например, отдельные вычислительные машины имеют специальное оборудование для подкачки выгруженных страниц памяти.
АРХИТЕКТУРА ОПЕРАЦИОННОЙ СИСТЕМЫ UNIX.
На Рис.58 представлена блок-схема ядра системы, отражающая состав модулей, из которых состоит ядро, и их взаимосвязи друг с другом. В частности, на ней слева изображена файловая подсистема, а справа подсистема управления процессами, две главные компоненты ядра. Эта схема дает логическое представление о ядре, хотя в действительности в структуре ядра имеются отклонения от модели, поскольку отдельные модули испытывают внутреннее воздействие со стороны других модулей.
Схема на Рис. 58 имеет три уровня: уровень пользователя, уровень ядра и уровень аппаратуры. Обращения к операционной системе и библиотеки составляют границу между
пользовательскими программами и ядром, проведенную на Рис.58. Обращения к операционной системе выглядят так же, как обычные вызовы функций в программах на языке Си, и библиотеки устанавливают соответствие между этими вызовами функций и элементарными системными операциями. При этом программы на ассемблере могут обращаться к операционной системе непосредственно, без использования библиотеки системных вызовов. Программы часто обращаются к другим библиотекам, таким как библиотека стандартных подпрограмм ввода-вывода, достигая тем самым более полного использования системных услуг. Для этого во время компиляции библиотеки связываются с программами и частично включаются в программу пользователя. Далее проиллюстрированы эти моменты на примере.
На рисунке совокупность обращений к операционной системе разделена на те обращения, которые взаимодействуют с подсистемой управления файлами, и те, которые взаимодействуют с подсистемой управления процессами. Файловая подсистема управляет файлами, размещает записи файлов, управляет свободным пространством, доступом к файлам и поиском данных для пользователей. Процессы взаимодействуют с подсистемой управления файлами, используя при этом совокупность специальных обращений к операционной системе, таких как open (для того, чтобы открыть файл на чтение или запись), close, read, write, stat (запросить атрибуты файла), chown (изменить запись с информацией о владельце файла) и chmod (изменить права доступа к файлу). Подсистема управления файлами обращается к данным, которые хранятся в файле, используя буферный механизм, управляющий потоком данных между ядром и устройствами внешней памяти. Буферный механизм, взаимодействуя с драйверами устройств ввода-вывода блоками, инициирует передачу данных к ядру и обратно. Драйверы устройств являются такими модулями в составе ядра, которые управляют работой периферийных устройств. Устройства ввода-вывода блоками относятся к типу запоминающих устройств с произвольной выборкой; их драйверы построены таким образом, что все остальные компоненты системы воспринимают эти устройства как запоминающие устройства с произвольной выборкой. Например, драйвер запоминающего устройства на магнитной ленте позволяет ядру системы воспринимать это устройство как запоминающее устройство с произвольной выборкой. Подсистема управления файлами также непосредственно взаимодействует с драйверами устройств "неструктурированного" ввода-вывода, без вмешательства буферного механизма. К устройствам неструктурированного ввода-вывода, иногда именуемым устройствами посимвольного ввода-вывода (текстовыми), относятся устройства, отличные от устройств ввода-вывода блоками.
Рис. 58. Блок-схема ядра операционной системы
Подсистема управления процессами отвечает за синхронизацию процессов, взаимодействие процессов, распределение памяти и планирование выполнения процессов. Подсистема управления файлами и подсистема управления процессами взаимодействуют между собой, когда файл загружается в память на выполнение: подсистема управления процессами читает в память исполняемые файлы перед тем, как их выполнить.
Примерами обращений к операционной системе, используемых при управлении процессами, могут служить fork (создание нового процесса), exec (наложение образа программы на выполняемый процесс), exit (завершение выполнения процесса), wait (синхронизация продолжения выполнения основного процесса с моментом выхода из порожденного процесса), brk (управление размером памяти, выделенной процессу) и signal (управление реакцией процесса на возникновение экстраординарных событий).
Модуль распределения памяти контролирует выделение памяти процессам. Если в какой-то момент система испытывает недостаток в физической памяти для запуска всех процессов, ядро пересылает процессы между основной и внешней памятью с тем, чтобы все процессы имели возможность выполняться. Есть два способа управления распределением памяти: выгрузка (подкачка) и замещение страниц. Программу подкачки иногда называют планировщиком, т.к. она "планирует" выделение памяти процессам и оказывает влияние на работу планировщика центрального процессора. Однако в дальнейшем мы будем стараться ссылаться на нее как на "программу подкачки", чтобы избежать путаницы с планировщиком центрального процессора.
Модуль "планировщик" распределяет между процессами время центрального процессора. Он планирует очередность выполнения процессов до тех пор, пока они добровольно не освободят центральный процессор, дождавшись выделения какого-либо ресурса, или до тех пор, пока ядро системы не выгрузит их после того, как их время выполнения превысит заранее определенный квант времени. Планировщик выбирает на выполнение готовый к запуску процесс с наивысшим приоритетом; выполнение предыдущего процесса (приостановленного) будет продолжено тогда, когда его приоритет будет наивысшим среди приоритетов всех готовых к запуску процессов. Существует несколько форм взаимодействия процессов между собой от асинхронного обмена сигналами о событиях до синхронного обмена сообщениями.
Наконец, аппаратный контроль отвечает за обработку прерываний и за связь с машиной. Такие устройства, как диски и терминалы, могут прерывать работу центрального процессора во время выполнения процесса. При этом ядро системы после обработки прерывания может возобновить выполнение прерванного процесса. Прерывания обрабатываются не самими процессами, а специальными функциями ядра системы, перечисленными в контексте выполняемого процесса. Модуль распределения памяти контролирует выделение памяти процессам. Если в какой-то момент система испытывает недостаток в физической памяти для запуска всех процессов, ядро пересылает процессы между основной и внешней памятью с тем, чтобы все процессы имели возможность выполняться. Есть два способа управления распределением памяти: выгрузка (подкачка) и замещение страниц. Программу подкачки иногда называют планировщиком, т.к. она "планирует" выделение памяти процессам и оказывает влияние на работу планировщика центрального процессора. Однако в дальнейшем мы будем стараться ссылаться на нее как на "программу подкачки", чтобы избежать путаницы с планировщиком центрального процессора.
Модуль "планировщик" распределяет между процессами время центрального процессора. Он планирует очередность выполнения процессов до тех пор, пока они добровольно не освободят центральный процессор, дождавшись выделения какого-либо ресурса, или до тех пор, пока ядро системы не выгрузит их после того, как их время выполнения превысит заранее определенный квант времени. Планировщик выбирает на выполнение готовый к запуску процесс с наивысшим приоритетом; выполнение предыдущего процесса (приостановленного) будет продолжено тогда, когда его приоритет будет наивысшим среди приоритетов всех готовых к запуску процессов. Существует несколько форм взаимодействия процессов между собой от асинхронного обмена сигналами о событиях до синхронного обмена сообщениями.
Наконец, аппаратный контроль отвечает за обработку прерываний и за связь с машиной. Такие устройства, как диски и терминалы, могут прерывать работу центрального процессора во время выполнения процесса. При этом ядро системы после обработки прерывания может возобновить выполнение прерванного процесса. Прерывания обрабатываются не самими процессами, а специальными функциями ядра системы, перечисленными в контексте выполняемого процесса.
ПРОЦЕССЫ
UNIX является и многопользовательской, и многозадачной системой. Достаточно мощный ЦП может выделить квант времени одной программе, затем переключиться на обслуживание другой, и так далее, что создает иллюзию одновременного выполнения ("квантование времени").
В каждый конкретный момент времени ОЗУ содержит не только объектный код активной программы, но и объектный код определенного числа приостановленных программ, а также различные области данных, содержащие промежуточные результаты этих программ. Большая часть ядра ОС (а иногда и все ядро) также должна быть резидентной в ОЗУ.
Более современный термин "многозадачность" включает в себя понятие мультипрограммирования, но расширяет эту концепцию и предполагает возможность одновременного выполнения отдельных частей одной и той же программы (которые называются нитями или потоками). Большинство программ можно интерпретировать как последовательность более мелких элементов, которые называются задачами. Иногда такие задачи должны выполняться синхронно, то есть выполняться и завершаться поочередно и по одной, так, например, для выполнения задачи 2 могут потребоваться результаты задачи 1. В других случаях некоторые или все задачи в программе могут выполняться независимо (или асинхронно). Есть, конечно, и смешанные ситуации.
Термины "программа" и "задача" довольно туманны: программный код теоретически и практически можно разбить на фрагменты по-разному. Программист может сформировать программу путем компиляции и компоновки множества мелких программ или модулей. При выполнении такие программы могут вызывать другие программы и подпрограммы, часть из которых могут представлять собой системные вызовы - предусмотренные в ОС базовые обслуживающие программы. Поэтому с одной стороны программа - это подготавливаемый программистом исходный код, с другой - скомпилированный двоичный файл на диске, а с третьей - двоичный код, находящийся в ОЗУ и ожидающий планирования.
Процесс и программа не идентичные понятия. Во-первых, существуют процессы, которым не соответствует никакой программы (т. е. исполняемого файла). Во-вторых, программа в ходе своего выполнения может породить более одного процесса. А в-третьих, при запуске программы порождение нового процесса (системный вызов fork) предшествует собственно запуску программы (системный вызов exec).
С технической точки зрения, образ программы представляет собой выполняемую программу в двоичном виде (которую не совсем верно называют сегментом текста), а также различные структуры данных, содержащие контекст программы, и две ее рабочих области - сегмент данных и стек. Упрощенная версия образа программы UNIX показана на рис.59.
Рис. 59. Схема образа программы
Когда вызывается какая-либо команда, командный процессор загружает образ программы (через вызов ядра) и начинает новый процесс с уникальным числовым идентификатором процесса (PID). Все последующие ссылки на этот процесс (как пользователей, так и других процессов) осуществляется через идентификатор процесса, а не имя исходной команды. Идентификаторы процессов 0 и 1 резервируются для специальных процессов, создаваемых при загрузке.
Если выполняемую команду вызывает другой пользователь, то создается новый процесс с другим идентификатором. Однако для нового процесса не всегда нужен новый образ программы, так как при выполнении одной и той же программы процессы могут совместно использовать сегмент текста ее образа.
Существуют, с одной стороны, процессы системные и прикладные, с другой — интерактивные и неинтерактивные. Первые порождаются ядром и не имеют соответствующих им программ (исполнимых файлов). Функция их, в первую очередь — управление виртуальной памятью, свопингом и т. д. К системным относят и процесс init. Это вызвано тем, что, хотя он и не является частью ядра, запускаясь из исполняемого файла, он является прародителем всех остальных процессов.
Все прочие протекающие в системе процессы относят, как правило, к категории прикладных. Они разделяются на процессы интерактивные или неинтерактивные (все системные процессы - неинтерактивны). Первые обычно порождаются в рамках пользовательского сеанса работы, привязаны к определенному терминалу (реальному или виртуальному - тому, с которого они стартовали) и имеют своего хозяина, т. е. запустившего процесс пользователя.
Неинтерактивные процессы именуются обычно демонами (daemon - Disk And Execution MONitor). Они инициируются самой системой при ее загрузке обычным образом (запуском соответствующих программ) и функционируют в фоновом режиме, активизируясь при требовании соответствующей функции (печати, доставки почты и т. д.). Не будучи при этом привязанными к какому-либо терминалу, реальному или виртуальному.
Каждый выполняемый процесс будет выбираться для выполнения согласно своему приоритету, который может устанавливаться и изменяться. Обычно процесс выполняется до завершения, а затем прекращает свое существование. Процесс может также завершиться в результате возникновения какой-то ошибки или сигнала (такого как kill) от пользователя или другого процесса. При завершении процесса он удаляется из таблицы процессов, а занятая им ОП освобождается для новых процессов.
Когда работает процесс А, он может порождать другой процесс, процесс В. Говорят, что процесс В является дочерним процессом процесса А, а процесс А называется родительским процессом. Помимо собственного идентификатора, каждый процесс имеет атрибут PPID, то есть идентификатор родительского процесса.
Атрибутами процесса являются:
- идентификатор процесса и его родителя;
- его приоритет;
- реальный и эффективный идентификаторы пользователя;
- реальный и эффективный идентификаторы группы пользователей.
Для получения информации о протекающих в системе процессах и их атрибутах служит команда ps.
ПРИОРИТЕТ И ЗНАЧЕНИЕ NICE.
От приоритета зависит, какую часть времени центрального процессора он получит. Выбирая процесс для выполнения, ядро находит процесс с самым высоким "внутренним приоритетом".
Непосредственно установить внутренний приоритет невозможно, но можно установить так называемое значение nice, которое существенно влияет на внутренний приоритет. Кроме того, внутренний приоритет зависит от того, сколько времени центрального процессора уже использовал процесс и от времени ожидания своей очереди на выполнение.
Значение nice подсказывает ядру, как следует относиться к данному процессу по сравнению с другими процессами, борющимися за время центрального процессора. Чем ниже nice процесса, тем выше его приоритет.
Если пользователь не предпринимает особых мер, то вновь созданный процесс наследует приоритет своего родительского процесса. Владелец процесса может увеличить значение nice, но не может уменьшить его. Это не дает возможности процессам с низким приоритетом производить на свет "высокоприоритетных детей". Но привилегированный пользователь имеет полную свободу в установке значений nice.
Для создания нового процесса существующий процесс копирует самого себя с помощью системного вызова fork (ветвь - отсюда "ветвление процессов"), который создает копию исходного процесса, идентичную родителю (например, у них идентичные копии первоначального ОЗУ), но имеются следующие отличия:
у нового процесса свой РID;
PРID нового процесса равен РID родителя;
учетная информация нового процесса обнулена;
у нового процесса имеется свой собственный экземпляр дескрипторов файлов.
Затем дочерний процесс вызывает один из системных вызовов семейства exec, используя при этом команды и аргументы (если они имеются), наследуемые из родительского процесса.
exec обновляет образ дочернего процесса так, что дочерний процесс начинает выполнение наследуемой команды. Он изменяет текст программы, которую выполняет процесс, и устанавливает сегменты данных и стека в исходное состояние. Когда вызывается одна из подпрограмм exec, она записывает в адресное пространство процесса содержимое нового программного файла, а затем возобновляет выполнение с означенной точки входа нового текста. После этого дочерний и родительский процессы могут идти своими путями и выполнять собственные операции (теперь это различные образы).
Когда система загружается, ядро самостоятельно создает несколько процессов. Наиболее важный из них - процесс init, PID которого всегда равен 1. Этот процесс отвечает за вызов shell для выполнения сценариев запуска (если они есть). Все процессы, кроме тех, которые создает ядро, являются потомками init.
Процесс init играет важную роль и в управлении процессами. Когда процесс завершается, он вызывает подпрограмму _exit, чтобы уведомить ядро о своей готовности "умереть". В качестве параметра подпрограмме _exit передается код завершения - целое число, указывающее на причину завершения процесса (нулевой код завершения означает, что процесс был "успешным").
Код завершения необходим родительскому процессу, поэтому ядро хранит его, пока родительский процесс не запросит его системным вызовом wait. Дело в том, что когда процесс завершается, его адресное пространство освобождается, время центрального процессора этому процессу не выделяется, однако в таблице процессов ядра запись о нем сохраняется. Процесс в этом состоянии называется "зомби".
Этот механизм работает нормально, если родительский процесс завершается позже порожденных им процессов и добросовестно вызывает wait для того, чтобы все процессы-зомби умерли. Если же родительский процесс умирает первым, то ядро понимает, что вызова wait не последует, и передает всех зомби процессу init. Тот обязан принять эти процессы и выполнить wait. Иногда init срабатывает некорректно, и зомби остаются в системе.
В ОС UNIX определено свыше тридцати различных видов сигналов. Сигнал - это способ сообщить процессу: "Произошло какое-то событие, поэтому брось делать то, что делаешь, и займись этим событием".
Возможен один из двух вариантов развития событий при поступлении сигнала. Если процесс назначил данному сигналу подпрограмму обработки, то вызывается эта подпрограмма, и предоставляется информация о контексте, в котором был выдан сигнал. В противном случае ядро выполняет от имени процесса действие, определенное по умолчанию.
Вызов подпрограммы обработки сигнала называют перехватом сигнала. По завершению подпрограммы обработки процесс возобновляется с той точки, где был получен сигнал.
Чтобы сигналы не поступали в процесс, можно указать, что они должны игнорироваться или блокироваться. Игнорируемый сигнал просто отбрасывается и не оказывает на процесс никакого влияния. Блокированный сигнал ставится в очередь на выдачу, но ядро не требует от процесса никаких действий до явного разблокирования сигнала.
Сигналы kill (разрушение принимающего процесса) и stop (приостановление принимающего процесса до получения сигнала cont) нельзя ни перехватить, ни блокировать. Сигнал cont можно перехватить и игнорировать, но нельзя блокировать.
Существует множество способов использования сигналов. Они могут посылаться одним процессом в другой для обеспечения связи, управляющим терминалом процесса для предоставления пользователю возможности прерывания или приостановки этого процесса, ядром в очень многих ситуациях и даже процессом самому себе.
Пять основных состояний процесса перечислены в таблице 6.
Состояние |
Смысл |
Выполнимый |
процесс можно выполнять |
Ожидающий |
процесс ждет выделения какого-либо ресурса |
Свопированный |
процесс отсутствует в памяти |
Зомби |
процесс пытается умереть |
Остановленный |
процесс приостановлен (не имеет разрешения на выполнение) |
Таблица 6. Основные состояния процесса.
Выполнимый процесс получил все необходимые ресурсы и ждет лишь выделения времени процессора для обработки данных. Если процесс порождает системный вызов, который нельзя выполнить немедленно (например, чтение части файла), система переводит его в состояние ожидания.
Ожидающий процесс ждет наступления определенного события. Интерпретатор команд пользователя и системные демоны проводят в этом состоянии большую часть своего времени, ожидая ввода с терминала или сетевого соединения. Так как ожидающий процесс фактически блокирован до удовлетворения его запроса, то время процессора будет выделено ему только в случае получения сигнала.
Свопированный процесс - это процесс, переписанный на диск и удаленный из ОП компьютера. Большинство систем свопируют процессы на диск, когда конкуренция за ОП столь сильна, что замещение страниц (paging) "захлебывается" и вместо того, чтобы делать полезную работу, система тратит неоправданно много времени на обработку прерываний, вызванную нехваткой страниц памяти. Строго говоря, свопированный процесс - не состояние процесса. Свопированный процесс может быть ожидающим, остановленным и даже номинально выполнимым; он остается замороженным в том состоянии, в котором он находился перед записью на диск, вплоть до возвращения в ОП.
Остановленный процесс - это процесс, выполнение которого запрещено. Процессы останавливаются при получении сигнала stop или tstp и перезапускаются сигналом cont. Это состояние аналогично ожиданию, но выйти из него можно только с помощью другого процесса.
