В следующем примере пользовательская программа, вызываемая как команда shell, выполняет в отдельном процессе стандартную команду shell ls, которая выдает на экран содержимое текущего каталога файлов.
main()
{if(fork()==0) wait(0); /* родительский процесс */
else execl("ls", "ls", 0); /* порожденный процесс */
}
4.5.2 Перенаправление ввода/вывода
Механизм перенаправления ввода/вывода является одним из наиболее элегантных, мощных и одновременно простых механизмов ОС.
Реализация механизма основывается на следующих свойствах ОС. Во-первых, любой ввод/вывод трактуется как ввод из некоторого файла и вывод в некоторый файл.
Клавиатура и экран терминала тоже интерпретируются как файлы (первый можно только читать, а во второй можно только писать).
Во-вторых, доступ к любому файлу производится через его дескриптор (положительное целое число).
Фиксируются три значения дескрипторов файлов. Файл с дескриптором 1 называется файлом стандартного ввода (stdin), файл с дескриптором 2 - файлом стандартного вывода (stdout), и файл с дескриптором 3 - файлом стандартного вывода диагностических сообщений (stderr). В-третьих, программа, запущенная в некотором процессе, "наследует" от породившего процесса все дескрипторы открытых файлов.
В наиболее распространенных функциях библиотеки ввода/вывода printf, scanf и error вообще не требуется указывать дескриптор файла.
Функция printf неявно использует stdout, функция scanf - stdin, а функция error - stderr.
4.5.3 Монтируемые файловые системы
Файлы любой файловой системы становятся доступными только после "монтирования" этой файловой системы. Файлы "не смонтированной" файловой системы не являются видимыми операционной системой.
Для монтирования файловой системы используется системный вызов mount. Монтирование файловой системы означает следующее. В имеющемся к моменту монтирования дереве каталогов и файлов должен иметься листовой узел - пустой каталог (в терминологии UNIX такой каталог, используемый для монтирования файловой системы, называется directory mount point - точка монтирования).
В любой файловой системе имеется корневой каталог. Во время выполнения системного вызова mount корневой каталог монтируемой файловой системы совмещается с каталогом - точкой монтирования, в результате чего образуется новая иерархия с полными именами каталогов и файлов.
Смонтированная файловая система впоследствии может быть отсоединена от общей иерархии с использованием системного вызова umount. Для успешного выполнения этого системного вызова требуется, чтобы отсоединяемая файловая система к этому моменту не находилась в использовании (т.е. ни один файл из этой файловой системы не был открыт). Корневая файловая система всегда является смонтированной, и к ней не применим системный вызов umount.
4.5.4 Интерфейс с файловой системой
Ядро ОС поддерживает для работы с файлами несколько системных вызовов. Среди них наиболее важными являются open, creat, read, write, lseek и close.
Файл в системных вызовах, обеспечивающих реальный доступ к данным, идентифицируется своим дескриптором (целым значением). Дескриптор файла выдается системными вызовами open (открыть файл) и creat (создать файл). Основным параметром операций открытия и создания файла является полное или относительное имя файла. Кроме того, при открытии файла указывается также режим открытия (только чтение, только запись, запись и чтение и т.д.) и характеристика, определяющая возможности доступа к файлу:
open(pathname, oflag [,mode])
Одним из признаков, которые могут участвовать в параметре oflag, является признак O_CREAT, наличие которого указывает на необходимость создания файла, если при выполнении системного вызова open файл с указанным именем не существует (параметр mode имеет смысл только при наличии этого признака
Открытый файл может использоваться для чтения и записи последовательностей байтов. Для этого поддерживаются два системных вызова:
read(fd, buffer, count) и write(fd, buffer, count)
Здесь fd - дескриптор файла (полученный при ранее выполненном системном вызове open или creat), buffer - указатель символьного массива и count - число байтов, которые должны быть прочитаны из файла или в него записаны. Значение функции read или write - целое число, которое совпадает со значением count, если операция заканчивается успешно, равно нулю при достижении конца файла и отрицательно при возникновении ошибок.
В каждом открытом файле существует текущая позиция. Сразу после открытия файл позиционируется на первый байт. Другими словами, если сразу после открытия файла выполняется системный вызов read (или write), то будут прочитаны (или записаны) первые count байтов содержимого файла (конечно, они будут успешно прочитаны только в том случае, если файл реально содержит по крайней мере count байтов). После выполнения системного вызова read (или write) указатель чтения/записи файла будет установлен в позицию count+1 и т.д.
Такой, чисто последовательный стиль работы, оказывается во многих случаях достаточным, но часто бывает необходимо читать или изменять файл с произвольной позиции (например, как без такой возможности хранить в файле прямо индексируемые массивы данных?). Для явного позиционирования файла служит системный вызов
lseek(fd, offset, origin)
Как и раньше, здесь fd - дескриптор ранее открытого файла. Параметр offset задает значение относительного смещения указателя чтения/записи, а параметр origin указывает, относительно какой позиции должно применяться смещение. Возможны три значения параметра origin. Значение 0 указывает, что значение offset должно рассматриваться как смещение относительно начала файла. Значение 1 означает, что значение offset является смещением относительно текущей позиции файла. Наконец, значение 2 говорит о том, что задается смещение относительно конца файла. Заметим, что типом данных параметра offset является long int. Это значит, что, во-первых, могут задаваться достаточно длинные смещения и, во-вторых, смещения могут быть положительными и отрицательными.
Например, после выполнения системного вызова
lseek(fd, 0, 0)
указатель чтения/записи соответствующего файла будет установлен на начало (на первый байт) файла. Системный вызов
lseek(fd, 0, 2)
установит указатель на конец файла. Наконец, выполнение системного вызова
lseek(fd, 10, 1)
приведет к увеличению текущего значения указателя на 10.
Естественно, системный вызов успешно завершается только в том случае, когда заново сформированное значение указателя не выходит за пределы существующих размеров файла.
4.5.5 Файлы-каталоги
Наличие обычных файлов недостаточно для организации иерархических файловых систем. Требуется наличие каталогов, которые сопоставляют имена файлов или каталогов с их физическим описанием. Каталоги представляют собой особый вид файлов, которые хранятся во внешней памяти подобно обычным файлам, но структура которых поддерживается самой файловой системой.
Структура файла-каталога очень проста. Фактически, каталог - это таблица, каждый элемент которой состоит из двух полей: номера i-узла данного файла в его файловой системе и имени файла, которое связано с этим номером (конечно, этот файл может быть и каталогом).
Файлам-каталогам соответствует особый тип файла (обозначенный в их i-узлах), по отношению к которому возможно выполнение только специального набора системных вызовов:
- getdents, позволяющего прочитать содержимое указанного каталога.
Отсутствует системный вызов, позволяющий прямо писать в файл-каталог.
4.5.6 Специальные файлы
Специальные файлы не хранят данные. Они обеспечивают механизм отображения физических внешних устройств в имена файлов файловой системы. Каждому устройству, поддерживаемому системой, соответствует, по меньшей мере, один специальный файл. Специальные файлы создаются при выполнении системного вызова mknod, каждому специальному файлу соответствует порция программного обеспечения, называемая драйвером соответствующего устройства. При выполнении чтения или записи по отношению к специальному файлу, производится прямой вызов соответствующего драйвера, программный код которого отвечает за передачу данных между процессом пользователя и соответствующим физическим устройством.
4.5.7 Связывание файлов с разными именами
Файловая система ОС обеспечивает возможность связывания одного и того же файла с разными именами.
Для работы с символьными связями поддерживаются три специальных системных вызова:
- readlink - читает имя файла, связанного с именуемой символической связью (это имя может соответствовать реальному файлу, специальному файлу, жесткой ссылке или вообще ничему); имя хранится в блоке данных, связанном с данной символической ссылкой;
- lstat - аналогичен системному вызову stat (получить информацию о файле), но относится к символической ссылке;
- lchowm - аналогичен системному вызову chown, но используется для смены пользователя и группы самой символической ссылки.
4.5.8 Файлы, отображаемые в виртуальную память
Для отображения файла в виртуальную память, после открытия файла выполняется системный вызов mmap, действие которого состоит в том, что создается сегмент разделяемой памяти, ассоциированный с открытым файлом, и автоматически подключается к виртуальной памяти. После этого процесс может читать из нового сегмента (реально будут читаться байты, содержащиеся в файле) и писать в него (реально все записи отображаются в файл). При закрытии файла соответствующий сегмент автоматически отключается от виртуальной памяти процесса и уничтожается, если только файл не подключен к виртуальной памяти некоторого другого процесса.
Несколько процессов могут одновременно открыть один и тот же файл и подключить его к своей виртуальной памяти системным вызовом mmap. Тогда любые изменения, производимые путем записи в соответствующий сегмент разделяемой памяти, будут сразу видны другим процессам.
4.5.9 Синхронизация при параллельном доступе к файлам
Ядро ОС поддерживает дополнительный системный вызов fcntl, обеспечивающий такие вспомогательные функции, относящиеся к файловой системе, как получение информации о текущем режиме открытия файла, изменение текущего режима открытия и т.д.
С помощью этого системного вызова можно установить монопольную или совместную блокировку файла целиком или блокировать указанный диапазон байтов внутри файла. Допускаются два варианта синхронизации: с ожиданием, когда требование блокировки может привести к откладыванию процесса до того момента, когда это требование может быть удовлетворено, и без ожидания, когда процесс немедленно оповещается об удовлетворении требования блокировки или о невозможности ее удовлетворения в данный момент времени.
Установленные блокировки относятся только к тому процессу, который их установил, и не наследуются процессами-потомками этого процесса. Более того, даже если некоторый процесс пользуется синхронизационными возможностями системного вызова fcntl, другие процессы по-прежнему могут работать с тем файлом без всякой синхронизации. Другими словами, это дело группы процессов, совместно использующих файл, - договориться о способе синхронизации параллельного доступа.
5 ФОРМИРОВАНИЕ БАЗЫ ДАННЫХ ОС
Совокупность данных, используемую ОС для управления процессами и ресурсами, называют базой данных ОС (БД ОС). Основная часть базы данных размещается в ядре системы, что обеспечивает ее надежную защиту.
Большая часть элементов базы данных создается и уничтожается динамически. Также динамически создаются и модифицируются связи между элементами. Поэтому для реализации БД ОС, как правило, используют многосвязные списочные структуры данных.
Основу базы данных составляют управляющие блоки, объединяемые в списки сложной структуры. Заголовки основных списков и некоторые глобальные системные переменные образуют статическую часть базы данных. Динамически создаваемые и уничтожаемые блоки размещаются в куче ядра (kernel heap).
Управляющие блоки создаются для каждого типа ресурсов, а также для каждого процесса и для элементов, обеспечивающих взаимодействие процессов. Управляющий блок содержит общее описание параметров ресурса/процесса, а также подробную информацию о текущем состоянии. Управляющие блоки одного типа могут объединяться в общий список (очередь), либо группироваться в несколько списков для различных состояний (очередь готовых процессов, очередь блокированных процессов).
5.1 Структура управляющих блоков базы данных ОС
База данных операционной системы содержит всю информацию, необходимую ей для функционирования. Она состоит из статической и динамической частей. Размер статической части не изменяется, а динамическая часть может изменять свой размер в процессе работы системы.
База данных состоит из следующих управляющих блоков:
- блок управления файлами;
- блок управления памятью;
- блок управления процессами.
При обращении к оперативной памяти блок управления памятью это регистрирует, определяет по ряду признаков возможность доступа и права пользователя, при завершении работы процесса с этим сегментом блок позволяет другому процессу найти этот сегмент.Блок управления устройствами регистрирует все устройства, их текущее состояние, при необходимости изменяет его в ходе работы.Блок управления файлами заносит запись об открытом файле в таблицу, устанавливает признаки, при закрытии файла запись удаляется из таблицы.
5.2 Схема взаимодействия управляющих блоков базы данных ОС
На рисунке 5.1 приведена схема взаимодействия управляющих блоков базы данных операционной системы.
Рисунок 5.1 – Взаимодействие управляющих блоков базы данных ОС
Блок управления процессами имеет следующую структуру:
- PID – ID процесса;
- NAME – имя процесса;
- QID – идентификатор очереди, в которой стоит процесс;
- ID – идентификатор пользователя;
- PRI – приоритет процесса;
- ST – текущее состояние процесса (0 – процесс находится в режиме исполнения, 1 – процесс находится в режиме ожидания, 2 - процесс находится в режиме готовности).
Блок управления памятью хранит информацию об оперативной памяти (располагается в статической части базы данных). Структура блока управления памятью имеет вид:
- RCB_HANDLE – дескриптор блока;
- RCB_SIZE – размер блока;
- RCB_CADR – текущий адрес блока;
- RCB_RIGHT – права доступу.
Блок управления файлами - динамическая часть базы данных, размер этого блока изменяется при изменении системной переменной, определяющей количество открытых файлов.
При открытии файла, в БД создается запись для этого файла, при его закрытии, он удаляется. Если с файлом работает несколько процессов одновременно, то все связи с процессами этого файла указываются.
Структура блока управления файлами представляет собой следующее:
- FCB_ID - ID файла;
- NAME - имя файла;
- SIZE - размер файла;
- TIME - время создания;
- BUSYBLOCKS - перечень блоков, занимаемых данным файлом.
Операционная система автоматически проверяет статус устройства. При отсутствии устройства, который был подключен, драйвер выгружается из памяти. При обнаружении нового устройства операционная система, получает данные об устройстве и загружает соответствующий драйвер. Каждое устройство имеет свой запрос на прерывание и порт ввода вывода. При загрузке драйвера ему сообщается эта информация, и дальнейшая работа с устройством ведется только с помощью драйвера.
Блок управления устройством содержит следующую информацию:
- DCB_ID - ID устройства;
- DCB_NAME - имя устройства;
- DCB_ST - статус устройства;
- DCB_INT - таблица точек входа;
- DCB_INIT - инициализация;
- DCB_WRITE - флаг записи;
- DCB_READ - флаг чтения;
- DCB_PROP - параметры устройства;
- DCB_DRV - адрес драйвера устройства;
- DCB_NEXT - адрес следующего DCB.
6 ПРОГРАММНАЯ РЕАЛИЗАЦИЯ
6.1 Средства взаимодействия процессов
Наличие механизмов взаимодействия дает произвольным процессам возможность осуществлять обмен данными и синхронизировать свое выполнение с другими процессами.
Процессы взаимодействуют посредствам семафоров.
Семафор представляет собой глобальный объект, позволяющий синхронизировать работу двух или нескольких процессов или потоков. Для программиста семафор - это просто счетчик. Если счетчик равен N, это означает, что к ресурсу имеют доступ N процессов. Рассмотрим функции для работы с семафорами:
– CreateSemaphor - создаёт глобальный объект-семафор. Возвращает дескриптор семафора.
HANDLE CreateSemaphore
{LPSECURITY_ATTRIBUTES lpSemaphoreAttributes,
LONG lInitialCount,
LONG lMaximumCount,
LPCTSTR lpName}
где, первый параметр - указатель на структуру, определяющую атрибуты доступа. Может иметь значение для Windows NT. Обычно данный параметр равен NULL.Второй параметр - начальное значение счётчика семафора. Определяет, сколько задач имеют доступ к ресурсу в начале.Третий параметр - количество задач, которые имеют одновременный доступ к ресурсу.Четвёртый параметр - указатель на строку, содержащую имя семафора.
– OpenSemaphor - открыть уже созданный семафор. Возвращает дескриптор семафора. Данную функцию используют не так часто. Обычно создают семафор и присваивают его дескриптор глобальной переменной, а потом используют этот дескриптор в порождаемых потоках.
HANDLE OpenSemaphore
{ DWORD dwDesiredAccess,
BOOL bInheritHandle,
LPCTSTR lpName}
Параметры функции: первый параметр - определяет желаемый уровень доступа к семафору. Возможны значения: SEMAPHORE_MODiFY_STATE = 2H, разрешить использование функции ReleaseSemaphore, SYNCHRONIZE = 100000H, разрешить использование любой функции ожидания, только для Windows NT, SEMAPHORE_ALLACCESS = 0F0000h+ SYNCHRONIZE+3H, специфицирует все возможные флаги доступа к семафору.
– WaitForSingleObject – ожидать открытие семафора. При успешном завершении, т. е. открытии доступа к объекту, функция возвращает 0. Значение 102h будет означать, что заданный период ожидания.
DWORD WaitForSingleObject
{HANDLE hHandle,
DWORD dwMilliseconds}
Первый параметр – дескриптор семафора.Второй параметр – время ожидания в миллисекундах. Если параметр равен INFINITE = 0FFFFFFFFh, то время ожидания не ограничено.
– ReleaseSemaphore – освободить семафор и позволить получить доступ к ресурсу другим процессам.
BOOL ReleaseSemaphore
{HANDLE hSemaphore,
LONG lReleaseCount,
LPLONG lpPreviousCount}
Первый параметр – дескриптор семафора. Второй параметр – определяет какое значение должно быть добавлено к счетчику семафора. Чаще всего этот параметр равен единице. Третий параметр – указатель на переменную, куда должно быть перемещено предыдущее значение счетчика.
На рисунке 6.1 представлена конфигурация выполняемых процессов.
Рисунок 6.1 – Конфигурация процессов
В каждой вершине представленного графа выполняются различные функции: 1 – IT, 2 – IT, 3 – IT, 4 – IT, 5 – IT, 6 – IT, 7 – SS, 8 – SS.
“начало” — начинает выполнение (результат всегда = 1);
“конец” — завершает выполнение– выводит на экран свой аргумент, закрывает все потоки, освобождает ресурсы;
SS — SS(Arg) – вычисление суммы ряда Σ ABS(sin(i)) для i от 1 до модуля Arg;
IT — IT(Arg) – вычисление определенного интеграла ABS(cos(x)*sin(x)) на интервале от -Arg до +Arg методом трапеций с разбиением на 100*Arg интервалов;
Arg = Σ Rez * Nblock * Nvar,
где, Σ Rez – сумма результатов входящих блоков; Nblock – номер блока в конфигурации.
Рассмотрим алгоритм работы с семафором. Сначала при помощи функции CreateSemaphore создадим семафор, и его дескриптор присваивается глобальной переменной. Пред попыткой обращения к ресурсам доступ, к которым необходимо ограничить, поток должен вызвать функцию WaitForSingleObject. При открытии доступа функция возвращает 0. По окончании работы с ресурсом следует вызвать функцию ReleaseSemaphor. Тем самым увеличивается счётчик доступа на 1. С помощью семафора можно регулировать количество потоков, которые одновременно могут иметь доступ к ресурсу. Максимальное значение счетчика как раз и определяет, сколько потоков могут получить доступ к ресурсу одновременно.
Листинг программного кода представлен в приложении В.
6.2 Реализация логики управления файловой системой
Организация файловой системы, применяемой в ОС, является UNIX. В результате выполнения курсового проекта был разработан эмулятор файловой системы UNIX. Который позволяет выполнять различные операции над файлами. Такими как запись, копирование, удаление а также удаление всех файлов сразу (Quick Format).
Рисунок 6.2 – Расположение файловой системы Unix
Расположение файловой системы на диске показано на рисунке 6.2. Все дисковое пространство, отведенное под файловую систему, делится на четыре области:
- загрузочный блок (boot), в котором хранится загрузчик операционной системы;
- суперблок (superblock) - содержит самую общую информацию о файловой системе: размер файловой системы, размер области индексных дескрипторов, число индексных дескрипторов, список свободных блоков и список свободных индексных дескрипторов, а также другую административную информацию;
- область индексных дескрипторов, порядок расположения индексных дескрипторов в которой соответствует их номерам;
- область данных, в которой расположены как обычные файлы, так и файлы-каталоги. Специальные файлы представлены в файловой системе только записями в соответствующих каталогах и индексными дескрипторами специального формата, но места в области данных не занимают.
Доступ к файлу осуществляется путем последовательного просмотра всей цепочки каталогов, входящих в полное имя файла, и соответствующих им индексных дескрипторов. Поиск завершается после получения всех характеристик из индексного дескриптора заданного файла. Эта процедура требует в общем случае нескольких обращений к диску, пропорционально числу составляющих в полном имени файла. Для уменьшения среднего времени доступа к файлу его дескриптор копируется в специальную системную область памяти.
Файловая система спроектирована по аналогии с UNIX и содержит её основные блоки:
а) Суперблок — 12 бит. Содержит:
- размер блока;
- размер индексного дескриптора;
- размер файловой системы.
б) Блок индексных дескрипторов — 64 бита. Содержит:
- имя файла;
- номер дескриптора;
- размер файла;
- десять блоков указующие на блоки данных;
- три блока содержащие косвенные дескрипторы.
в) Блок данных. Размер блоков задается при создании образа файловой системы.
Спецификация команд эмулятора:
а) Create(char *img_name, int size, int size_blocks) — создаёт файл-образ с именем img_name, размером size, параметр size_blocks — указывает на размер блоков данных файловой системы.
б) CopyFromHDD(char *img_name, char *file) — копирует в файл-образ с именем img_name файл с жесткого диска с именем file.
в) CopyToHDD(char *img_name,char *file, char *fileToHDD) — копирует из файла-образа (img_name) файл с именем file на жесткий диск. FileToHDD — задает имя итогового файла.
г) Delete (char *img_name, char *file) — удаляет с файла-образа (img_name) файл с именем file.
д) Format (char *img_name) — форматирует файл-образ (img_name).
е) ShowRoot — показывает информацию о файловой системе и выводит информацию о файлах содержащихся в ней.
Листинг программного кода представлен в приложении В.
7 ОПРЕДЕЛЕНИЕ СОСТАВА И ОБЩЕЙ СТРУКТУРЫ ОС
Основное назначение мультипрограммной ОС - обеспечить исполнение множества процессов, совместно использующих ресурсы компьютера. Поэтому ключом к пониманию функционирования ОС является диаграмма состояний процесса.
Ядро ОС обеспечивает создание мультипроцессной среды и исполнение системных вызовов (примитивов) управления процессами, оперативной памятью и устройствами. Общая схема работы ядра раскрывает порядок выполнения основных системных вызовов и обработки прерываний. Так как язык системных вызовов реализуется, как правило, посредством механизма программных прерываний, ядро ОС является, по-существу, совокупностью обработчиков прерываний.
7.1 Структура системы
Операционная система взаимодействует с аппаратурой непосредственно, обеспечивая обслуживание программ и их независимость от деталей аппаратной конфигурации. Если представить систему состоящей из пластов, в ней можно выделить системное ядро, изолированное от пользовательских программ. Поскольку прикладные программы не зависят от аппаратного устройства исполняющей их машины, то они могут быть перенесены из одной системы в другую (учитывая, что в этих программах не предусмотрена работа с некоторым точно определенным оборудованием).
Программы, подобные командному процессору, взаимодействуют с ядром при помощи хорошо определенного набора обращений к операционной системе. Обращения к операционной системе понуждают ядро к выполнению различных операций, которых требует вызывающая программа, и обеспечивают обмен данными между ядром и программой. Другие прикладные программы располагаются выше указанных программ, на верхнем уровне.
Самый общий взляд на архитектуру UNIX позволяет увидеть двухуровневую модель системы, состоящую из пользовательской и системной части – ядра(рисунок 7.1). Ядро непосредственно взаимодействует с аппаратной частью компьютера, изолируя прикладные программы (процессы в пользовательской части операционной системы) от особенностей ее архитектуры. Ядро имеет набор услуг, предоставляемых прикладным программам посредством системных вызовов. Таким образом, в системе можно выделить два уровня привилегий: уровень системы (привилегии специального пользователя root).
Рисунок 7.1 Архитектура операционной системы
Важную часть системных программ составляют демоны. Демон — это процесс, выполняющий опеределенную функцию в системе, который запускается при старте системы и не связан ни с одним пользовательским терминалом. Демоны предоставляют пользователям определенные сервисы, примерами которых могут служить системный журнал, веб-сервер и т. п.
7.2 Первоначальная загрузка
Для того, чтобы перевести систему из неактивное состояние в активное, администратор выполняет процедуру "начальной загрузки". На разных машинах эта процедура имеет свои особенности, однако во всех случаях она реализует одну и ту же цель: загрузить копию операционной системы в основную память машины и запустить ее на исполнение.
В системе UNIX процедура начальной загрузки заканчивается считыванием с диска в память блока начальной загрузки (нулевого блока). Программа, содержащаяся в этом блоке, загружает из файловой системы ядро ОС. После загрузки ядра системы в память, ядро запускается на выполнение.
7.3 Файловая система ОС
Рассмотрим ключевые особенности данной системы. Итак, файлы характеризуются:
- Иерархической структурой;
- согласованной обработкой массивов данных;
- возможностью создания и удаления файлов;
- защитой информации в файлах и т.д.
Файловая система представляет собой дерево, с единственной основой – корнем (root), обозначающимся как, а воглаве этого главного корня стоит главный супер администратор с логином "root" по умолчанию. Каждая вершина в древовидной структуре файловой системы, кроме листьев, является каталогом файлов, а файлы, соответствующие дочерним вершинам, являются либо каталогами, либо обычными файлами, либо файлами устройств.
Каталоги похожи на обычные файлы в том смысле, что система представляет информацию в каталоге набором байтов, но эта информация включает в себя имена файлов в каталоге в объявленном формате.
7.4 Устройства
Для пользователя система UNIX трактует устройства так, как если бы они были файлами. Устройства, для которых назначены специальные файлы устройств, становятся вершинами в структуре файловой системы. Обращение программ к устройствам имеет тот же самый синтаксис, что и обращение к обычным файлам; семантика операций чтения и записи по отношению к устройствам в большой степени совпадает с семантикой операций чтения и записи обычных файлов. Способ защиты устройств совпадает со способом защиты обычных файлов.