
- •Операционные системы для программиста
- •Введение
- •1. Основные понятия
- •1.1. Понятие операционной системы
- •1.2. Системные соглашения для доступа к функциям ос
- •1.3. Особенности разработки программ в базовых ос
- •1.4. Командный интерфейс пользователя в ос
- •1.5. Информация об ошибках системной функции
- •2. Программный доступ к файловой системе
- •2.1. Понятия дескрипторов, идентификаторов и хэндлов
- •2.2. Ввод и вывод в стандартные файлы.
- •2.3. Базовые средства использования файлов
- •2.4. Многопользовательская блокировка файлов
- •2.5. Установка произвольной позиции в файле
- •3. Принципы построения ос
- •3.1. Модульная структура построения ос
- •3.2. Использование прерываний в ос
- •3.3. Управление системными ресурсами
- •3.4 Строение ядра операционной системы
- •3.5. Структура операционной системы типа Windows nt
- •4. Многофункциональный консольный вывод
- •4.1. Функции управления курсором
- •4.2. Многократный вывод символов и атрибутов
- •4.3. Вывод в произвольную позицию экрана
- •4.4. Ввод данных, размещенных предварительно на экране
- •5. Системные функции ввода для консольных устройств
- •5.1. Системные функции ввода текстовых строк
- •5.2. Событийно-управляемый ввод
- •5.3. Системные функции ввода с клавиатуры
- •5.4. Опрос ввода с клавиатуры в программе
- •5.5. Системные функции мыши для текстового режима
- •6. Файловые системы
- •6.1. Структуры файловых систем для пользователя
- •6.2. Методы распределения внешней памяти
- •6.3. Принципы построения файловых систем типа fat
- •6.4. Современные модификации файловой системы fat
- •6.5. Особенности построения файловой системы hpfs
- •6.6. Принципы построения файловой системы ntfs
- •6.7. Особенности строения файловых систем для Unix
- •6.8. Программный опрос файловой системы
- •7. Обеспечение множественности процессов
- •7.1. Основные понятия теории вычислительных процессов
- •7.2. Программное порождение процессов
- •7.3. Уничтожение процессов
- •7.4. Ожидание завершения процессов
- •8. Многопоточное функционирование ос
- •8.1. Понятие нити и связь Хе с процессом
- •8.2. Создание нитей (thread) в программе
- •8.3. Уничтожение нитей
- •8.4. Приостановка и повторный запуск нити
- •8.5. Ожидание завершения нити
- •9. Средства взаимодействия программных единиц
- •9.1. Абстрактные критические секции
- •9.2. Абстрактные семафоры
- •9.3. Семафоры взаимоисключения
- •9.4. Семафоры событий
- •9.5. Средства группового ожидания
- •9.6. Программные критические секции
- •9.7. Программные семафоры с внутренним счетчиком
- •10. Управление памятью
- •10.1. Виртуальная память
- •10.2. ЏодкРчка страниц для реализациШ виртуальной памяти
- •10.3. Системные функции распределения памяти
- •10.4. Совместное использование памяти
- •10.5. Отображение файлов в оперативную память
- •10.6. Динамически распределяемая память
- •11. Средства коммуникации процессов
- •11.1. Неименованные коммуникационные каналы Unix
- •11.2. Переназначение хэндлов для доступа к каналу
- •11.3. Неименованные каналы в Windows
- •11.4. Именованные каналы в Windows nt
- •11.5. Именованные каналы в Unix
- •12. Взаимодействие пользователя с ос
- •12.1. Интерфейсы операционных систем
- •12.2. Командные и операционные оболочки (shells)
- •12.3. Основные команды базовых операционных систем
- •12.4. Групповое выполнение и фоновый запуск команд
- •12.5. Стандартный ввод-вывод и конвейеры командной строки
- •12.6. Командные файлы и сценарии
- •Библиографический список
2. Программный доступ к файловой системе
2.1. Понятия дескрипторов, идентификаторов и хэндлов
Операционная система управляет множеством информационных объектов, необходимых для осуществления ее функций. Простейшей разновидностью этих объектов, присутствующих даже в самых примитивных ОС, являются файлы. В многозадачной ОС число типов таких объектов приближается к десяти, а вместе с типами объектов графической оболочки их оказывается еще больше. Мы будем изучать внутренние объекты операционной системы постепенно, отталкиваясь от понятия файла. Напомним, что файлом называется именованный информационный объект, хранимый в компьютере даже тогда, когда последний выключен. Иначе говоря, файл – это информационный объект длительного хранения, имеющий наименование, легко доступное пользователю, и который может быть перенесен с одного внутреннего места хранения в другое, в частности с одного компьютера на другой или просто на внешний носитель информации (например дискету).
С файлами программист встречается с первых своих шагов, но ему не заметно, как собственно операционная система справляется с обслуживанием файлов. В то же время с этих первых шагов ему становится известно, что для использования файла в программе его нужно открыть. Широко известным, хотя часто не замечаемым фактом, является то, что в цивилизованном обществе управлять людьми и экономическими объектами оказывается возможным только с помощью учетной информации, в качестве которой используются паспорта и документы. Аналогично этому во внутреннем мире операционной системы для управления теми же файлами создается и используется учетная информация, которую называют File Control Block или другим аналогичным образом. Терминологическое обозначение может меняться от одной ОС к другой, так как зависит от произвола создателей такой истемы. Для нас главное, что управление файлами при их "внутрикомпьютерной жизни" использует аналоги паспорта. Когда файл просто записан на дискете или жестком диске, в такой учетной информации нет необходимости.
По существу открытие файла и заключается в создании управляющего блока. Для ясного представления желательно знать, что содержится в этом блоке. Там, как минимум, содержится информация о следующем месте чтения из файла или записи в файл. (Напомним, что чтение из файла и запись в него автоматически выполняются последовательно, как на магнитную ленту, от использования которой файлы и произошли.) Программистам известно, что место следующего обращения к файлу можно изменить с помощью специальной функции, обычно называемой SEEK или каким-либо производным от этого слова. В действительности такие функции приводят к изменению параметра именно в управляющем блоке файла, но вовсе не в самом файле. Другим параметром управляющего блока файла служит вид доступа, задаваемый при его открытии (будет ли использоваться файл для чтения, для записи или обеих этих операций). В действительности управляющий блок файла может содержать и, как правило, содержит информацию о месте размещения файла или начале его размещения, позволяющую быстро добраться до его содержимого, но такая информация более важна для внутренних процедур работы с файлами и мы на ней не будем заострять внимание.
Управляющий блок файла – это служебная структура данных, необходимая для управления файлом средствами операционной системы. У вдумчивого программиста возникает вопрос, где же находится эта информация. Возможны два принципиальных решения его: эти структуры данных могут находиться в пределах самой исполняемой программы (ее области данных) и описываться в ней, либо размещаться в служебных областях, доступных только операционной системе. Первое решение использовалось в ранних ОС и помимо дополнительных усилий от программиста (по заданию экземпляров таких структур) оно имело такой недостаток, как возможность непреднамеренного изменения данных структур в результате ошибок программиста и его программы. Поэтому от него, как более трудоемкого и, главное, менее надежного решения, позже отказались. (В частности, в первых версиях MS DOS были системные функции работы с файлами с помощью FCB блоков, которые существовали и позже, но настойчиво не рекомендовались для использования.)
Практическая реализация второго подхода к размещению управляющих блоков файлов появилась вначале в ОС Unix и базируется на понятии хэндла. В этом подходе управляющие блоки размещаются в служебной области операционной системы, причем, как правило, в виде таблицы, и для доступа к ним используется номер строк такой таблицы (порядковый номер управляющего блока во внутренней таблице управляющих блоков для выполняемой программы). Этот номер строк таблицы управляющих блоков и называют handle. Иным наименованием для хэндла, использовавшимся как раз в Unix, служит слово дескриптор или (в русском переводе) описатель. Термин "дескриптор", хотя и является традиционным в операционной системе Unix, на самом деле вызывает ложные аналогии. В действительности его целесообразней применять как синоним управляющего блока, так как именно в последнем содержится учетная информация, описывающая файл и необходимая для выполнения файловых операций. Для операций над файлом при обращении к системной функции в качестве одного из параметров вызова используется значение такого хэндла. По этому значению подпрограмма ОС обращается к соответствующей строке таблицы управляющих блоков и использует информацию из управляющего блока, отвечающего этой строке.
Таким образом, хэндл с внешней (поверхностной) стороны – просто некоторый специальный номер для выполнения операций с конкретным открытым файлом. Более существенным его пониманием, важным для более сложных ситуаций использования, должно быть осознание, что на самом деле этому номеру – хэндлу однозначно соответствует строка специальной таблицы управляющих блоков, которая и дает необходимую информацию для оперативной работы с файлом. Заметим, что английское слово handle переводится на русский язык как ручка, рукоять, но в этом "родном" значении оно не привилось в технической информатике (оказывается удобней использовать чисто фонетический перенос исходного названия вместо применения оборотов русского технического языка вроде "возьмем ручку файла", хотя для англоязычного слушателя и читателя этот оборот звучит именно так).
В переводной технической литературе по программированию встречается перевод термина handle словом идентификатор. (Заметим, что последнее слово также не русского происхождения.) Этим закладывается некоторая сумятица в умы начинающих программистов, так как сложившееся использование термина identificator относится к принципиально иным информационным объектам. Идентификатор позволяет однозначно обозначить некоторый объект. Хэндлы же различных по содержанию и собственному названию файлов могут быть одинаковыми. Причем одинаковыми в один и тот же момент работы компьютера. Такие ситуации имеют место, когда в компьютере выполняется несколько программ одновременно (несколько программ начали свое выполнение, но еще не завершились). В этих выполняемых программах очень часто оказываются одинаковые значения хэндлов (как номеров строк текущих таблиц дескрипторов) по той причине, что для каждой выполняемой программы (точнее вычислительного процесса) операционная система создает и поддерживает свою собственную таблицу дескрипторов файлов. Поэтому одинаковые номера строк таких таблиц содержат различную информацию.
В некоторых ОС термин идентификатор (правда для более сложных объектов, чем дескриптор файла) используется независимо от термина хэндл и обозначает действительно уникальное в данной операционной системе условное обозначение сложного объекта. Позже идентификаторы сложных системных объектов будут рассматриваться при изучении параллельных процессов в современных операционных системах.