Для типового компьютера клавиатура является главным средством ввода информации, а дисплей — главным средством вывода. Знание особенностей представления информации в них является необходимым фактором умения работы с машиной. Различают три уровня представления и обработки сигналов, поступающих с клавиатуры: физический, логический и функциональный.
Физический уровень имеет дело с сигналами, которые поступают в системный блок при нажатии и отпускании клавиш. При нажатии любой клавиши в системный блок посылается код, соответствующий ее порядковому номеру, который называют скан-кодом клавиши (от англ. 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"
.
Далее во всех командах числовой аргумент обозначается буквой 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).
Написать программу со следующим алгоритмом:
- получить из стека командную строку (содержащую имя файла и параметры, переданные программе при запуске);
- первый параметр вывести на экран красным цветом, второй — синим и с новой строки.
- выполнить побайтный «переворот» содержимого файла, имя которого задано первым параметром командной строки; информацию записывать в этот же файл без промежуточных и дополнительных файлов, с использованием отображения файла на память;
- каждая файловая операция контролируются на ошибку без анализа ее номера с выдачей на терминал своего сообщения, типа «Ошибка открытия файла», «Ошибка записи» и т.д.
- завершить программу.