- •Операционные системы
- •1. Назначение и функции операционных систем. История развития
- •1.1. Основные функции операционных систем
- •1.2. Эволюция ос
- •1.2.1. Первый период (1945 -1955)
- •1.2.2. Второй период (1955 - 1965)
- •1.2.3. Третий период (1965 – 1980)
- •1.2.4. Четвертый период (1980 - настоящее время)
- •2. Классификация операционных систем
- •2.1. Классификация ос в зависимости от особенностей алгоритмов управления ресурсами
- •2.1.1. Поддержка многозадачности
- •2.1.2 Поддержка многопользовательского режима
- •2.1.3 Вытесняющая и невытесняющая многозадачность
- •2.1.4 Поддержка многонитевости.
- •2.1.5 Наличие механизма многопроцессорной обработки
- •2.2. Классификация ос в зависимости от особенностей аппаратных платформ
- •2.3. Классификация ос по областям использования
- •2.4. Особенности методов построения ос
- •3. Управление процессами
- •3.1. Состояния процессов
- •3.2. Контекст и дескриптор процесса
- •3.3. Алгоритмы планирования процессов
- •3.4. Средства синхронизации и взаимодействия процессов
- •3.4.1. Проблема синхронизации
- •3.4.2 Критическая секция
- •3.4.3 Тупики
- •3.4.4 Нити
- •4. Управление памятью
- •4.1. Типы адресов
- •4.2. Методы распределения памяти без использования дискового пространства
- •4.2.1. Распределение памяти фиксированными разделами
- •4.2.2. Распределение памяти разделами переменной величины
- •4.2.3. Перемещаемые разделы
- •4.3 Методы распределения памяти с использованием дискового пространства
- •4.3.1. Понятие виртуальной памяти
- •4.3.2. Страничное распределение
- •4.3.3. Сегментное распределение
- •4.3.4. Странично-сегментное распределение
- •4.3.5. Свопинг
- •4.4. Иерархия запоминающих устройств. Принцип кэширования данных
- •5. Управление вводом-выводом
- •5.1. Физическая организация устройств ввода-вывода
- •5.2. Организация программного обеспечения ввода-вывода
- •5.2.1. Обработка прерываний
- •5.2.2. Драйверы устройств
- •5.2.3. Независимый от устройств слой операционной системы
- •5.2.4. Пользовательский слой программного обеспечения
- •6. Файловая система
- •6.1. Правила именования и типы файлов
- •6.2. Логическая организация файла
- •6.3. Физическая организация и адрес файла
- •6.4. Права доступа к файлу
- •6.5. Кэширование диска
- •6.6. Общая модель файловой системы
- •6.7. Современные архитектуры файловых систем
- •7. Управление распределенными ресурсами
- •7.1. Базовые примитивы передачи сообщений в распределенных системах
- •7.2. Способы адресации
- •7.3. Блокирующие и неблокирующие примитивы
- •7.4. Буферизуемые и небуферизуемые примитивы
- •7.5. Надежные и ненадежные примитивы
- •8. Современные концепции проектирования операционных систем
- •8.1. Расширяемость
- •8.2. Переносимость
- •8.3. Совместимость
- •8.4. Безопасность
- •9. Варианты построения информационных приложений
- •9.1. Типовые компоненты информационных приложений
- •9.2. Централизованные многотерминальные системы
- •9.3. Файл-серверные приложения
- •9.4. Приложения клиент-сервер
- •9.5. Распределенные вычисления
- •9.6. Офисные системы
- •9.7. Информационные системы на основе Internet/Intranet-технологии
- •10. Концепции windows nt
- •10.1 Структура: nt-executive и защищенные подсистемы
- •10.2. Множественные прикладные среды в Windows nt
- •10.3. Объектно-ориентированный подход в Windows nt
- •10.4. Процессы и нити
- •10.5. Алгоритм планирования процессов и нитей
- •10.6. Сетевые средства Windows nt
- •10.7. Совместимость линейки операционных систем Windows nt с Novell NetWare
- •Оглавление
7.3. Блокирующие и неблокирующие примитивы
Примитивы бывают блокирующими (синхронными) и неблокирующими (асинхронными). При использовании блокирующего примитива, процесс, выдавший запрос на его выполнение, останавливается до завершения примитива. Например, вызов примитива «ПОЛУЧИТЬ» останавливает вызывающий процесс до получения сообщения.
При использовании неблокирующего примитива управление возвращается вызывающему процессу немедленно. Преимуществом этой схемы является параллельное выполнение вызывающего процесса и процесса передачи сообщения. Обычно в ОС имеется один из двух видов примитивов и очень редко оба.
Однако выигрыш в производительности при использовании неблокирующих примитивов компенсируется серьезным недостатком: отправитель не может изменить буфер сообщения, пока сообщение не отправлено, а узнать, отправлено ли сообщение, отправитель не может.
Из этой ситуации имеется два выхода. Первый – заставить ядро копировать сообщение в свой внутренний буфер, затем разрешить процессу продолжаться. Второй – прервать процесс-отправитель после отправки сообщения для информирования его о доступности буфера.
В системе с блокирующим вызовом «ПОСЛАТЬ» при отсутствии ответа процесс может заблокироваться навсегда, поэтому в некоторых системах задается временной интервал (тайм-аут), в течение которого он ждет ответ. Если за это время сообщение не поступает, вызов «ПОСЛАТЬ» выдает ошибку.
7.4. Буферизуемые и небуферизуемые примитивы
Примитивы, которые были описаны являются небуферизуемыми. Это значит, что вызов «ПОЛУЧИТЬ» сообщает ядру выполняющей машины адрес буфера, в который поместить сообщение.
Эта схема работает при условии, что получатель выполняет вызов «ПОЛУЧИТЬ» раньше, чем отправитель выполняет вызов «ПОСЛАТЬ». Вызов «ПОЛУЧИТЬ» сообщает ядру выполняющей машины, по какому адресу поступает ожидаемое сообщение, и в какую область памяти его поместить.
Проблема возникает когда вызов «ПОСЛАТЬ» сделан раньше вызова «ПОЛУЧИТЬ». Как ядро на машине получателя узнает, какому процессу адресовано вновь поступившее сообщение, если их несколько? И как оно узнает, куда его скопировать?
Можно просто отказаться от сообщения, позволить отправителю взять тайм-аут и надеяться, что получатель все-таки выполнит вызов «ПОЛУЧИТЬ» перед повторной передачей сообщения. Этот подход не сложен в реализации, но, к сожалению, отправитель может сделать несколько таких безуспешных попыток. Еще хуже то, что после большого числа безуспешных попыток отправитель может сделать неправильный вывод об аварии на машине получателя или о неправильности использованного адреса.
Второй подход к этой проблеме заключается в том, чтобы хранить хотя бы некоторое время, поступающие сообщения в ядре получателя на тот случай, что вскоре будет выполнен соответствующий вызов «ПОЛУЧИТЬ». Каждый раз, когда поступает такое неожидаемое сообщение, включается таймер. Если заданный временной интервал истекает раньше, чем происходит соответствующий вызов «ПОЛУЧИТЬ», то сообщение теряется.
Процесс, ждущий сообщения, обращается к ядру с запросом о создании для него почтового ящика и сообщает адрес, по которому ему могут поступать сетевые пакеты, после чего все сообщения с данным адресом будут помещены в его почтовый ящик. Такой способ называют буферизуемым примитивом.