
- •Операционные системы для программиста
- •Введение
- •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. Командные файлы и сценарии
- •Библиографический список
3.5. Структура операционной системы типа Windows nt
Структура операционных систем типа Windows NT укрупненно представлена на рис. 3.1.
На схеме блоки "Клиент Win32" и "Клиент POSIX" представляют пользовательские процессы, использующие ОС, но в саму операционную систему не входят. Слой абстрагирования (Hardware Abstraction Layer) представляет собой совокупность программ, работающих непосредственно с аппаратурой, и его реализация зависит непосредственно от типа используемых процессоров. Этот слой изолирует верхние слои ОС от платформенно-зависимых особенностей аппаратуры.
Рис. 3.1. Упрощенная структура ОС типа Windows NT
Структура ОС Windows NT распадается на две существенно отличные части, верхняя по изображенной схеме работает в обычном пользовательском режиме аппаратуры, а нижняя - в состоянии режима ядра. Переход к режиму ядра на уровне машинных команд осуществляется с помощью прерываний. При этом принципиально меняются возможности использования некоторых операций, в частности появляется возможность непосредственно работать с аппаратурой.
Часть этой ОС, работающая в режиме ядра, за исключением слоя HAL разработчики назвали исполнительной системой (NT executive). В этом наименовании, в частности, отразилась традиция Microsoft, связанная с предшествующей квази-операционной системой Windows 3.x, в которой основная часть, отличная от графической оболочки, называлась подобным образом.
Все остальные блоки рассматриваемой схемы, за исключением клиентов, HAL и блока "Средство локального вызова процедур", в процессе функционирования представляют собой отдельные процессы, причем процессы исполнительной части и естественно привилегированные. Средства локального вызова представляют собой специализированные средства межпроцессного взаимодействия, ориентированные на взаимодействие процессов самой операционной системы.
Заметим, что в поздних версиях операционной системы Windows NT сервер графической системы, обозначаемый как программный компонент GDI (Graphic Device Interface), перемещен из области пользовательского режима в область ядра. Это сделано, начиная с ОС Windows 2000. Такое решение призвано ускорить видимые операции графического интерфейса, но принципиально снижает надежность всей операционной системы.
4. Многофункциональный консольный вывод
4.1. Функции управления курсором
Классические языки высокого уровня не содержат средств управления позицией вывода на экране и цветом символов текста. Такая ситуация в значительной степени предопределена тем, что когда создавались эти языки, подобные средства были недоступны по аппаратным причинам. Именно глубокая связь упомянутых возможностей с конкретной аппаратурой и привела к тому, что подобные средства оказались зависимыми от операционной системы. К настоящему времени подавляющее большинство мониторов поддерживают как позиционирование курсора, так и многоцветные изображения, но особенности управления этими возможностями по-прежнему оказываются зависимыми от операционных систем.
С содержательно-функциональной стороны для позиционирования (установки в некоторую позицию) курсора необходимо задать экранные координаты этой позиции. Наиболее просто и естественно это задается в OS/2. Здесь для этих целей служила функция с прототипом
APIRET16 VioSetCurPos(USHORT row, USHORT col, HVIO hvio).
Заметим, что все функции, осуществляющие управление экраном в этой ОС, имели префиксом названия буквосочетание Vio и возвращали 16-битное значение кода возврата, определяющее успешное выполнение функции как нулевое значение, ненулевые значения зарезервированы для кодов ошибок. Аргументами этой функции служили номера строки и столбца, в которые требовалось установить текстовый курсор. Последний аргумент hvio предполагалось использовать при множестве мониторов, подключенных к одному системному блоку компьютера. При единственном мониторе этот параметр должен быть равен 0. (Теоретически его задает хэндл монитора, для которого выполняется позиционирование.)
Обратной функцией к описанной являлась функция с прототипом
APIRET16 VioGetCurPos(USHORT *prow, USHORT *pcol, HVIO hvio).
Она возвращала значения номеров строки и столбца, в которых находится курсор.
Существенно отличается позиционирование курсора в ОС Windows. Здесь функция позиционирования имеет прототип
BOOL SetConsoleCursorPosition(HANDLE hConsOut, COORD pos).
Первым ее аргументом служит хэндл экрана консоли, а второй задает устанавливаемую позицию курсора и представляет собой структуру данных, описанную в заголовочном файле wincom.h как
typedef struct _COORD {
SHORT X;
SHORT Y;
} COORD, *PCOORD;
Ее использование требует от программиста несколько больших усилий. Так, например, установка курсора в третью строку и пятый столбец при работе в OS/2 требует единственной записи вызова функции в виде VioSetCurPos(3, 5, 0), а аналогичное указание позиции курсора для консоли ОС Windows вынуждает предварительно описать экземпляр структуры типа COORD, например в виде
COORD pos;
а затем задать запись целых трех операторов
pos.X=5; pos.Y=3;
SetConsoleCursorPosition(hout, &pos);
Обратная к установке функция, позволяющая определить текущую позицию курсора, описывается в Windows прототипом
BOOL GetConsoleScreenBufferInfo(HANDLE hConsOut,
CONSOLE_SCREEN_BUFFER_INFO* pConsoleScreenBufferInfo)
и требует использования структуры данных, описанной в заголовочном файле как
typedef struct _CONSOLE_SCREEN_BUFFER_INFO {
COORD dwSize;
COORD dwCursorPosition;
WORD wAttributes;
SMALL_RECT srWindow;
COORD dwMaximumWindowSize;
} CONSOLE_SCREEN_BUFFER_INFO, *PCONSOLE_SCREEN_BUFFER_INFO;
В этой структуре данных для рассматриваемых целей поле dwCursorPosition предоставляет информацию о положении курсора.
В операционной системе Unix для управления курсором и некоторых других действий с экраном предназначены управляющие последовательности. Идея их использования расширяет управляющие символы, которые в языке Си и Unix служат основным средством управления выводом на экран. Управляющие последовательности определяются стандартом ANSI и называются также ANSI-последовательностями. Их можно использовать и в других ОС, но там часто для этого оказывается необходимым запустить ANSI-драйвер. В MS DOS этот драйвер должен был быть установлен в конфигурационном файле CONFIG.SYS, в OS/2 – запущен как отдельная программа ANSI.EXE.
Управляющие последовательности ANSI начинаются со специального символа с десятичным эквивалентом значения 27. Это код, выдаваемый клавишей Esc, и при записи на языке Си в составе текстовых констант его записывают в виде '\033'. При этом задействована универсальная форма записи произвольных (в том числе явно не изображаемых символов) в виде восьмеричных констант. Вторым символом управляющих последовательностей ANSI является обязательный символ ‘[‘ (открывающаяся квадратная скобка), последним символом управляющей последовательности – латинская буква, детализирующая операцию. Иногда для такой детализации используется и предпоследний символ.
Для задания установки курсора служит управляющая последовательность, записываемая на языке Си как текстовая константа
"\033[строка;столбецH"
Здесь компоненты строка и столбец должны быть обязательно заданы десятичными числами и обязательно без дополнительных пробелов. В дальнейшем записывать управляющие последовательности (как принято в документации) будем без подразумеваемых кавычек, а служебный символ \033 условно записывать как esc, подразумевая, что это все-таки не три латинских буквы подряд, а один специальный символ. Нумерация позиции считается от 1, так что установка в верхний левый угол экрана требует последовательности esc[1;1H .
Для чтения позиции курсора имеется также специальная управляющая последовательность, но использование ее не очень удобно, а главное в ней практически нет необходимости при наличии таких интересных и удобных управляющих последовательностей, какие просто переводят курсор на заданное число строк и столбцов в вертикальном и горизонтальном направлениях. Для этих целей предназначены управляющие последовательности esc[строкаA, esc[строкаB, esc[столбецC, esc[столбецD, последние символы в которых обязательно прописные латинские буквы.
Последовательность esc[строкаA приказывает переместить курсор на заданное в ней число строк вверх, последовательность esc[строкаB – на заданное число строк вниз, esc[столбецC – на заданное в ней число столбцов вправо, а esc[столбецD – на заданное число столбцов влево. Если при заданных значениях параметров курсор должен выйти за пределы экрана, то действие управляющей последовательности игнорируется.