- •Операционные системы для программиста
- •Введение
- •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. Командные файлы и сценарии
- •Библиографический список
5.4. Опрос ввода с клавиатуры в программе
В ряде ситуаций при построении программы возникает необходимость получать информацию о том, нажимались ли клавиши клавиатуры во время выполнения данной программы или, иначе говоря, есть ли сообщения от клавиатуры, которые предполагается использовать несколько позже. В архаичной MS DOS для этих целей использовалась библиотека системных функций системно-зависимой версии языка Си, которая содержала функцию kbhit (в ориентированном на MS DOS Турбо Паскале аналогичная функция называлась keypressed).
В операционной системе OS/2 соответствующая функция (ожидания нажатия на любую клавишу клавиатуры) носила название KbdPeek и имела прототип
APIRET16 KbdPeek(KBDKEYINFO *pkbdi, HKBD hkbd),
причем информация о том нажата ли клавиша, возвращалась в одном из полей структуры данных типа KBDKEYINFO.
В операционных системах Windows проверка нажатия, точнее в более конкретных для этой ОС терминах, проверка наличия сообщений для функции ReadConsoleInput, может проводиться функцией PeekConsoleInput, имеющей прототип
BOOL PeekConsoleInput(HANDLE hConsInput,
INPUT_RECORD* buffer, DWORD len, DWORD* actlen).
Строение обращения этой функции практически полностью совпадает со строением обращения к функции ReadConsoleInput, и возвращают эти функции практически одно и то же. Различие между ними в том, что функция чтения ReadConsoleInput извлекает (из специальной очереди) очередное сообщение, поэтому следующее по выполнению обращение к этой же функции извлеченное сообщение не найдет (может быть извлечено только следующее сообщение, когда оно появится). Функция же PeekConsoleInput хотя и копирует информацию о событии в свой буфер, но не извлекает ее из очереди. Поэтому повторное выполнение той же функции найдет и извлечет уже использованное значение сообщения. В частном случае, когда сообщения от клавиатуры на момент выполнения функции PeekConsoleInput нет, она возвращает (без ожидания и приостановки процесса выполнения программы) с помощью последнего параметра, что присутствует нулевое число сообщений ввода.
В Windows есть еще одна функция, которую можно использовать для опроса наличия сообщений, но уже без детализации, что это сообщение содержит. Это функция GetNumberOfConsoleInputEvents с прототипом
BOOL GetNumberOfConsoleInputEvents(HANDLE hConsInput, DWORD* number).
Она выдает в качестве результата с помощью параметра number число сообщений ввода, накопившихся во входном буфере консоли. Если режим ввода выбран так, что к выполняемой программе поступают только сообщения от клавиатуры, то это значение можно использовать как информацию о нажатой клавише.
В операционной системе Unix нет непосредственных аналогов рассмотренных функций опроса нажатия клавиши. Аналогичную содержательную проблему такого специального получения символа из потока данных, чтобы он по-прежнему как бы оставался невостребованным и извлекаемым по следующей операции ввода, разработчики Unix решили очень оригинальным и своеобразным способом. Набор функций посимвольного ввода содержит функцию ungetc(int char, FILE *stream), которая возвращает прочитанный символ обратно в буфер ввода. Таким образом рассмотренные функции опроса ввода моделируются в Unix парой последовательных функций getc(FILE *stream) и ungetc(), между которыми или после которых можно поставить анализ введенного символа. Все же надо отметить, что описанная замена не обеспечивает полной аналогии. В частности, указанные функции относятся к произвольным потокам файловых данных, а не только к консоли.
Иногда, прежде чем опрашивать клавиатуру на предмет нажатия клавиш, нужно отбросить хранящиеся во входном буфере ненужные коды клавиш. Для этих целей служит функция очистки буфера клавиатуры. Она бывает нужна, когда программа начинает выполняться, а во внутреннем буфере, может быть, осталась какая-то символьная информация от клавиатуры, попавшая туда в конце выполнения предыдущей программы.
В операционной системе Windows такая функция имеет прототип
BOOL FlushConsoleInputBuffer(HANDLE hConsInput).
Целесообразно использовать эту функцию в начале программы работы с консолью, чтобы символы введенные до запуска программы в текстовом окне, не повлияли на ее нормальную работу.