Skip to content

Latest commit

 

History

History
191 lines (114 loc) · 17.3 KB

lab09term.textile

File metadata and controls

191 lines (114 loc) · 17.3 KB

Лабораторная работа №8. Управление отображением вывода в терминал ОС GNU/Linux

Краткие теоретические сведения

Системные инструменты

Представление информации в устройствах стандартного ввода/вывода

Для типового компьютера клавиатура является главным средством ввода информации, а дисплей — главным средством вывода. Знание особенностей представления информации в них является необходимым фактором умения работы с машиной. Различают три уровня представления и обработки сигналов, поступающих с клавиатуры: физический, логический и функциональный.

Физический уровень имеет дело с сигналами, которые поступают в системный блок при нажатии и отпускании клавиш. При нажатии любой клавиши в системный блок посылается код, соответствующий ее порядковому номеру, который называют скан-кодом клавиши (от англ. scan-code). При отпускании клавиши также генерируется ее номер, увеличенный на 128 (дополнительный скан-код).

На логическом уровне, реализуемом базовой подсистемой ввода-вывода ОС, происходит трансляция поступающего с клавиатуры скан-кода для отображения на дисплее соответствующего символа.

На функциональном уровне отдельным клавишам приписываются определенные функции, которые реализуются при нажатии этих клавиш.

Во времена создания UNIX для работы с ЭВМ использовались телетайпные терминалы. Терминал находился далеко от компьютера и был связан с ним кабелем по последовательному интерфейсу. Отображение информации на терминале можно было настроить с помощью посылки набора байтов к каждому из них. Всеми возможностями терминалов можно управлять специальными escape-последовательностями — особыми наборами байтов, которые начинаются с символа escape («эскейп», сокращенно «ESC», код 0×1B). В наши дни, работая с программами эмуляции терминала (для краткости их обычно называют просто «терминалами»), мы можем послать на стандартный вывод escape-последовательность, и это будет иметь тот же эффект, что и на аппаратном терминале.

Наберите на вашей консоли следующее:

echo "^[[0;31;40mIn Color"

Первый символ является символом escape, и выглядит как два символа: ^ и [. Что бы ввести этот символ, вам необходимо нажать CTRL+V и потом клавишу ESC (впрочем, сочетание клавиш может зависеть от программы-терминала). Все остальные символы являются обычными печатными. Вы увидите строку «In Color» красного цвета. Консоль так и останется в режиме красного цвета, и чтобы вернуть обычное состояние, надо ввести теперь:

echo "^[[0;37;40m"

Как можно видеть, достаточно просто устанавливать и сбрасывать цвет. Существует большое число escape-последовательностей, с помощью которых вы можете выполнять множество вещей: перемещать курсор, сбрасывать терминал и т. п.

Последовательность для установки цветов

Последовательность, которая должна быть выведена на терминал для установки цветов, следующая:

<ESC>[{attr};{fg};{bg}m

Первый символ это ESC, который вводится нажатием CTRL+V и ESC на Linux-консоли или же в xterm, konsole, kvt, и т.д. («CTRL+V ESC» можно применять и в текстовом редакторе vim для вставки символа ESC). Далее {attr}, {fg}, {bg} должны быть заменены верными значениями для получения соответствующего эффекта. Далее, attr это атрибут, вроде мигания или подчёркивания, а fg и bg — цвета символов и фона соответственно. Вам не нужно брать номера в фигурные скобки. Просто напишите их, этого достаточно.

{attr} может принимать следующие значения:

0 сбросить все атрибуты (вернуться в нормальный режим)
1 яркий (обычно включает жирный шрифт)
2 тусклый
3 подчёркнутый
5 мигающий
7 инверсный
8 невидимый

{fg} может принимать следующие значения:

30 чёрный
31 красный
32 зелёный
33 жёлтый
34 синий
35 фиолетовый
36 голубой
37 белый

{bg} может принимать следующие значения:

40 чёрный
41 красный
42 зелёный
43 жёлтый
44 синий
45 фиолетовый
46 голубой
47 белый

Так, для получения мигающего синего текста на зелёном фоне нужно вывести комбинацию echo "^[[5;34;42mIn color", а вернуть все назад можно комбинацией echo "^[0;37;40m".

Команды (esc-последовательности) syscons

Далее во всех командах числовой аргумент обозначается буквой n или n1,n2 и т. д., если их может быть несколько, Esc обозначает символ escape, а все остальные буквы являются частью команды.

При этом если команда требует числовой аргумент (или несколько), его можно пропустить. В этом случае обычно подразумевается, что он равен 1.

Esc7 или Esc[s запомнить положение курсора
Esc8 или Esc[u восстановить запомненное положение курсора
Escc очистить экран и установить курсор в левый верхний угол

Перемещение курсора:

lp9cm

Esc[nA & вверх на n строк
Esc[nB или Esc[ne & вниз на n строк
Esc[nC или Esc[na & вправо на n позиций
Esc[nD & влево на n позиций
Esc[nE & в начало строки и на n строк вниз
Esc[nF & в начало строки и на n строк вверх
Esc[n1;n2f или Esc[n1;n2H & переместить в позицию n1 и строку n2
Esc[nZ & на n табуляций назад (как Tab, но в обратную сторону)
Esc[n` & в той же строке в позицию n
Esc[nd & в той же позиции в строку n
EscM & сдвинуть курсор на строчку вверх, если он был в самой верхней строке, то сдвинуть содержимое экрана на строчку вниз (то же самое, что делает NewLine, только «вверх ногами»)

Очистка части экрана:

Esc[0J от курсора до конца экрана
Esc[1J от начала экрана до курсора
Esc[2J весь экран
Esc[0K от курсора до конца строки
Esc[1K от начала строки до курсора
Esc[2K всю строку
Esc[nX очистить n знаков от позиции курсора

«Раздвижка», «сдвижка», «прокрутка»:

Esc[nL вставить n пустых строк (те, что были — раздвинуть)
Esc[nM удалить n строк (те, что остались — «схлопнуть»)
Esc[nP удалить n знаков в строке (те, что остались — «схлопнуть»)
Esc[n@ вставить n знаков в строку (те, что были — раздвинуть)
Esc[nS прокрутить содержимое экрана на n строк вверх
Esc[nT прокрутить содержимое экрана на n строк вниз

Другие команды:

lp12cm

Esc[nz & переключится в виртуальный терминал n
Esc[=n1;n2B & установить параметры встроенного динамика — «пищалки»

n1 = частота (точнее, делитель для частоты), n2 = длительность (стандартные значения – 800;1); влияет на «писк», который получается при выводе символа Bell — 7; параметры свои для каждого виртуального терминала

Esc[=nC & тип курсора (действует на все виртуальные терминалы)

в n младший бит определяет мерцание (1 - да, 0 - нет)

следующий бит это тип курсора (аппаратно-генерируемый, если 0, или «символьный», если 1)
Esc[=n1;n2C & форма «символьного» курсора (для каждого виртуального терминала своя); закрашиваются строчки с n1 по n2 (начиная сверху) в матрице знака, которым рисуется курсор

Элементы программирования

Отображение файла в память

Помимо стандартного чтения файла в буфер заданными порциями байт в Linux существует еще как минимум один способ получить доступ к его содержимому: отображение файла на область памяти (функция mmap).

Механизм его работы следующий. Как только происходит обращение к памяти по указателю, который возвратила функция mmap, автоматически загружаются данные с диска в файловый кэш (если они еще не в кэше) и делается отображение (mapping) кэша на адресное пространство программы, после чего программе дается право на чтение этих данных.

Это позволяет программисту вообще не заботиться об оптимизации работы с диском — все это берет на себя механизм виртуальной памяти Linux. В любом случае происходит экономия и памяти, и скорости (за счет отсутствия копирования из кэша в буфер приложения). Это особенно заметно в случае обращения к одним и тем же данным несколькими приложениями.

Для работы с отображением файлов в память используются функции mmap (отображение памяти, системный вызов 90) и munmap (отмена отображения памяти, системный вызов 91):

void * mmap(void *start, size_t length, int prot , int flags, int fd,
            off_t offset); 
int  munmap(void *start, size_t length); 

Функция mmap отражает length байтов, начиная со смещения offset файла (или другого объекта), определенного файловым описателем fd, в память, начиная с адреса start. Последний параметр (адрес) необязателен, и обычно бывает равен 0. Настоящее местоположение отраженных данных возвращается самой функцией mmap, и никогда не бывает равным 0. Аргумент prot описывает желаемый режим защиты памяти (он не должен конфликтовать с режимом открытия файла). Оно является либо PROT_NONE, либо побитовым ИЛИ одного или нескольких флагов PROT_*:

PROT_NONE=0 доступ к этой области памяти запрещен.
PROT_READ=1 данные можно читать;
PROT_WRITE=2 в эту область можно записывать информацию;
PROT_EXEC=4 данные в страницах могут исполняться;

Параметр flags задает тип отражаемого объекта, опции отражения и указывает, принадлежат ли отраженные данные только этому процессу или их могут читать другие. Он состоит из комбинации следующих битов:

MAP_SHARED=1 — разделить использование этого отражения с другими процессами, отражающими тот же объект. Запись информации в эту область памяти будет эквивалентна записи в файл.

MAP_PRIVATE=2 — создать неразделяемое отражение с механизмом copy-on-write. Запись в эту область памяти не влияет на файл. Не определено, являются или нет изменения в файле после вызова mmap видимыми в отраженном диапазоне.

fd должно быть корректным описателем файла. offset должен быть пропорционален размеру страницы виртуальной памяти (например 0).

При удачном выполнении mmap возвращает указатель на область с отраженными данными. При ошибке возвращается значение MAP_FAILED (-1).

Задание для выполнения

Написать программу со следующим алгоритмом:

  • получить из стека командную строку (содержащую имя файла и параметры, переданные программе при запуске);
  • первый параметр вывести на экран красным цветом, второй — синим и с новой строки.
  • выполнить побайтный «переворот» содержимого файла, имя которого задано первым параметром командной строки; информацию записывать в этот же файл без промежуточных и дополнительных файлов, с использованием отображения файла на память;
  • каждая файловая операция контролируются на ошибку без анализа ее номера с выдачей на терминал своего сообщения, типа «Ошибка открытия файла», «Ошибка записи» и т.д.
  • завершить программу.