небольшую проверку ошибок для определения доступности стандартного
устройства вывода.
ЧТО ДЕЛАЕТ c?
Программа 'c' выводит на экран символ очистки настолько быстро,
насколько быстро может выполняться операция ввода-вывода в UNIX. При-
меняя прямой системный вызов, мы избавляемся от необходимости за-
пускать другую программу. Поэтому программа 'c' работает очень быстро.
Мы уверены, что точно такую же функцию можно вызывать как команду
Си-shell (поместить в csh alias), поэтому данная программа наиболее
полезна тем, кто работает в System V.
Для того чтобы определить, какой символ очистки соответствует ва-
шему терминалу, найдите строку с обозначением cl в файле termcap. Это
и есть то значение, которое вы должны вручную вставить в данную прог-
рамму. Если вы работаете не на таком терминале, для которого эта прог-
рамма написана, то данная команда будет работать неверно.
ПОЯСНЕНИЯ
Первым делом мы должны найти в файле termcap код очистки экрана.
Для терминала Apple это код ^L, а для vt52 это \EH\EJ. Как только вы
найдете этот код, вставьте его в оператор define в строке 3 или сразу
в оператор write в строке 7. В приведенном примере в качестве символа
очистки экрана используется ^L.
Наиболее быстрым способом передачи символа в файл является не-
посредственное выполнение оператора write. Поскольку терминалы явля-
ются файлами, мы можем выполнять запись непосредственно в них, пользу-
ясь преимуществом предопределенных дескрипторов файла 0,1 и 2.
Системный вызов write в строке 7 посылает символ очистки в файл с
дескриптором 1, который является стандартным устройством вывода. Если
операция записи неудачна (по ряду причин), то в файл с дескриптором 2,
т.е. на стандартное устройство регистрации ошибок, выводится сообщение
об ошибке. Здесь не проверяется, успешно ли завершилась запись на
стандартное устройство регистрации ошибок. Если ошибка все-таки воз-
никнет, то мы ее увидим.
Программа не использует НИКАКИХ возможностей стандартного вво-
да-вывода (stdio). НИКОГДА нельзя смешивать системные вызовы ввода-вы-
вода (т.е. вызовы из раздела (2) документации по системным функциям,
например read или write) со стандартными вызовами ввода-вывода (т.е.
вызовами из раздела (3), такими как getchar и printf). Дополнительный
буфер, который создается при выполнении функций stdio, не согласован
во времени с системными вызовами, поэтому все выходные сообщения пере-
мешиваются.
Еще один аспект, о котором мы должны помнить, принимая решение об
использовании системных вызовов, это преимущество получения как можно
более короткого объектного кода. Небольшая программа загружается и ра-
ботает быстрее. Для того, чтобы ненужные подпрограммы стандартного
ввода-вывода не включались в наш объектный модуль, в исходном тексте
программы не делается никаких ссылок на подпрограммы stdio. Тем не ме-
нее, ваша система могла их каким-то образом включить. Так поступает
XENIX, а вместе с stdio вызывается malloc и все остальное. Вы можете
просмотреть таблицу символов вашего объектного модуля с помощью nm(1)
или nlist(2). Вы увидите весь мусор, который был добавлен в ваш объек-
тный модуль. Не так редко мы получаем 6 Кб кода всего лишь для одного
оператора printf! Приучайтесь программировать непосредственно на
ассемблере, чтобы достичь того, что вам нужно.
ИССЛЕДОВАНИЯ
Когда эта программа была написана, возник вопрос: "Каким образом
мы можем проверить неудачу записи на стандартное устройство вывода?".
Раньше такой вопрос не стоял, но показалось, что неплохо было бы это
сделать. Решение было найдено на страницах описания sh(1). Способ, ко-
торым можно вызвать ошибку выполнения записи на стандартное устройство
вывода, заключается в том, что нужно закрыть дескриптор файла стан-
дартного устройства вывода. Это легко делается с помощью команды exec,
которая является внутренней по отношению к shell:
$ exec >&-
Эта команда переназначает файловый дескриптор 1 стандартного вы-
вода (обозначение >) на дескриптор файла (&) закрытого устройства (-).
Такой эксперимент может оказаться полезным для более полной отладки
ваших программ.
ДИСКОВЫЕ УСТРОЙСТВА
К дисковым устройствам относятся гибкие и жесткие диски. Каждый
диск может быть разделен на одну или несколько частей, каждая из кото-
рых связана с файлом устройства.
Основное отличие между дисками и терминалами заключается в том,
что диски являются блочными устройствами, а терминалы - символьными.
Вместо того, чтобы выполнять обмен информацией по одному символу,
диски обмениваются блоками по 512 или 1024 символа. Имеются команды,
которые управляют разбиением на блоки и буферизацией, что делает воз-
можным выполнение блочных операций ввода-вывода.
РАЗБИЕНИЕ ДИСКОВ НА РАЗДЕЛЫ
Части, или области диска, известны как разделы. Раздел может со-
держать файловую систему, которая сгенерирована командой mkfs(1), или
же может содержать неструктурированные данные, доступ к которым выпол-
няется с помощью команды 'cpio -o'.
В системе XENIX управление разделами осуществляется программой
fdisk, которая концептуально подобна своей тезке в системе MS-DOS. В
других системах UNIX используются другие имена. Например, в системе
AT&T 7300 UNIX PC используется программа iv, что значит "format" (хо-
тите верьте, хотите нет). Как упоминалось ранее, обычно разделы содер-
жат одну файловую систему. В настоящее время в системах XENIX и SCO
XENIX у вас есть возможность "разделить раздел" на более мелкие части
для получения большего количества файловых систем. Это сделано по той
причине, что машины с системами DOS и XENIX ограничены четырьмя диско-
выми разделами, а у вас может возникнуть желание иметь больше файловых
систем, чем число доступных разделов. В системе AT&T 7300 UNIX PC уп-
равление разделами диска осуществляется по списку начальных номеров
дорожек. Вы можете создать столько разделов, сколько хотите. Каждый
компьютер имеет свои преимущества и недостатки.
В каталоге /dev находятся имена как блочных устройств, так и сим-
вольных. По этим именам вызываются различные драйверы устройств. Ниже
приводится пример списка интерфейсов жестких дисков.
---------------------------------------------------------------------------
|
| brw------- 1 sysinfo sysinfo 1, 0 Feb 18 17:07 /dev/hd00
| brw------- 1 sysinfo sysinfo 1, 15 Feb 18 16:59 /dev/hd01
| brw------- 1 sysinfo sysinfo 1, 23 Feb 18 16:59 /dev/hd02
| brw------- 1 sysinfo sysinfo 1, 31 Feb 18 16:59 /dev/hd03
| brw------- 1 sysinfo sysinfo 1, 39 Feb 18 16:59 /dev/hd04
| brw------- 1 sysinfo sysinfo 1, 47 Feb 18 17:07 /dev/hd0a
| brw------- 1 sysinfo sysinfo 1, 55 Feb 18 17:09 /dev/hd0d
| crw------- 1 sysinfo sysinfo 1, 0 Feb 18 16:59 /dev/rhd00
| crw------- 1 sysinfo sysinfo 1, 15 Feb 18 16:59 /dev/rhd01
| crw------- 1 sysinfo sysinfo 1, 23 Feb 18 16:59 /dev/rhd02
| crw------- 1 sysinfo sysinfo 1, 31 Feb 18 16:59 /dev/rhd03
| crw------- 1 sysinfo sysinfo 1, 39 Feb 18 16:59 /dev/rhd04
| crw------- 1 sysinfo sysinfo 1, 47 Feb 18 16:59 /dev/rhd0a
| crw------- 1 sysinfo sysinfo 1, 55 Feb 18 17:09 /dev/rhd0d
|
Имена файлов с префиксом hd указывают блочные устройства, а с
префиксом rhd - "неструктурированные" символьные устройства. Не все
символьные устройства являются неструктурированными блочными уст-
ройствами. Терминалы являются символьными устройствами, как мы уже ви-
дели ранее в данной главе. В табл. 7-2 показаны различные характе-
ристики этих двух типов устройств.
Таблица 7-2
Сравнение блочных и символьных устройств
---------------------------------------------------------------------------
Блочное устройство Символьное устройство
---------------------------------------------------------------------------
/dev/hd0, /dev/fd0 /dev/rhd0, /dev/rfd0
буфер управляется ядром буферизация отсутствует,
системы, медленное устройство быстрое устройство
произвольное размещение последовательное размещение
блоков данных блоков данных
доступ через файловую доступ непосредственно
систему на диск
cpio -p cpio -o, -i
mkfs, mount, df, du tar
fsck, fsdb
---------------------------------------------------------------------------
Как видите, существует много способов работы с устройствами.
Давайте рассмотрим устройство /dev/hd01 из приведенного выше
списка. Если вы хотите адресоваться к физическому разделу на диске как
к блочному устройству, вы можете создать на нем файловую систему. Для
этого вам нужно выполнить следующую команду, которая создаст файловую
систему размером 5000 Кб (5 Мб) на жестком диске:
# mkfs /dev/hd01 5000
Внутри раздела (размером не менее 5000 Кб) размещается файловая
система. Файловая система содержит суперблок, списки свободных блоков
и т.п., то есть все, что необходимо для хранения файлов, которые раз-
мещаются здесь. Однако, создание файловой системы совсем НЕ означает,
что вы сразу же можете получить к ней доступ. Сначала вам необходимо
смонтировать файловую систему. Команда для выполнения этой операции
может иметь такой вид:
# mount /dev/hd01 /mount_pt
Файлы могут быть помещены в дисковый раздел командами mv или cp,
путем переадресации вывода в каталог с этим именем, например,
>/mount_pt/file.
Для использования раздела диска в качестве области неструктуриро-
ванных данных, а не блочного устройства, применяйте файл с именем сим-
вольного устройства, которое начинается с буквы r. Например, для
использования того же устройства, что и в предыдущем примере, в ка-
честве неструктурированного устройства, укажите имя /dev/rhd01. (Из
списка устройств вы видите, что это символьное устройство, так как
права доступа в первой колонке начинаются с символов crw, а не brw).
Это устройство (и соответствующий раздел) в данный момент не имеет
файловой системы и является просто набором байтов. Единственным огра-
ничением является то, что вы можете записать в этот раздел не более 5
Мб данных.
Вот пример команды, использующей неструктурированное устройство:
$ find . -print | cpio -ocBv > /dev/rhd01
ИЗУЧЕНИЕ ДАННЫХ
Когда данные находятся на диске, их можно изучить более тщатель-
но, чем с помощью команд cat, more и других. Делается это командой
od(1), которая выдает дамп файла устройства, как показано в следующем
примере:
$ od -c /dev/hd01
Если бы вы получали дамп файла НЕСТРУКТУРИРОВАННОГО устройства
(/dev/rhd01), то это выглядело бы точно так же. Единственное отличие
заключается в том, как драйвер осуществляет доступ к данным. Формат, в
котором будут выводиться данные, зависит от того, какой командой про-
изводилось копирование: cpio, tar, mkfs или какой-то иной. Некоторые
другие способы получения данных с устройства:
$ cat /dev/hd01
$ cat < /dev/hd01
$ tail /dev/fd0
Если вы дампируете файл устройства, содержащего файловую систему,
то данные будут представлять собой неупорядоченные блоки по 512 байт.
В одном месте вы можете увидеть списки каталогов. Другими словами, од-
но и то же устройство может рассматриваться двумя совершенно разными
способами: как файловая система и как набор неструктурированных битов.
Хотя выполнение чтения двумя этими способами может быть поучительным,
в большинстве случаев у вас не возникнет желания выполнить ЗАПИСЬ ин-
формации на одно и то же устройство двумя способами, поскольку, напри-