Материал: 6262

Внимание! Если размещение файла нарушает Ваши авторские права, то обязательно сообщите нам

31

1.3 Создание специальных файлов

Перед изучением данного вопроса следует повторить материал темы 4 «Управление файловыми системами ОС» [4], в частности:

подраздел 4.4, где описывается структура файловой системы FAT32;

подраздел 4.5, где описывается структура файловой системы EXT2FS;

подраздел 4.11, где уточняется основная идея виртуальной файловой системы (VFS).

Сама VFS реализована в ядре ОС и все операции с файлами осуществляются в пространстве ее представлений.

Фактически, VFS, как показано на рисунке 1.11, является виртуальным коммутатором всех внешних файловых систем, подключенных (монтированных) к ней.

В идейном плане, структура VFS очень близка к структуре EXT2FS, которая и является прямым ее прототипом.

Напомним, что структурную основу EXT2FS, как и других файловых систем Linux/UNIX, играет таблица индексных дескрипторов (Inode Tables), каждая строка которой содержит полное описание файла, кроме его имени:

когда файл создается в файловой системе, то ему выделяется отдельная строка в Inode Tables;

номер этой строки i-узел (inode) и используется для дальнейшей работы с

файлом, а имя файла и значение его i-узела записываются в соответствующий файл директории, имеющий записи переменной длинны (см. далее таблицу 1.1);

когда файл открывается, то VFS находит по имени файла значение i-узела,

запоминает его значение и возвращает пользователю номер дескриптора файла;

пользователь, обращаясь к файлу, указывает его дескриптор файла, а VFS по номеру дескриптора находит значение i-узела файла.

Таблица 1.1 - Структура записи переменной длины файла каталога

Название поля

Тип

Описание

inode

ULONG

Номер индексного дескриптора (индекс) файла

rec_len

USHORT

Длина этой записи

name_len

USHORT

Длина имени файла

name

CHAR[0]

Первый символ имени файла

Чтобы убедиться, что все файлы имеют свой номер i-узела, можно воспользоваться командой: ls -ia [имя_файла]

32

Рисунок 1.11 — Архитектурное представление ФС ОС Linux

Например, на рисунке 1.12 показано применение этой команды к домашней директории пользователя upk.

Замечание

Обратите внимание на специальные имена файлов, имеющиеся в каждом каталоге:

имя «.» имеет номер i-узла текущего каталога;

имя «..» имеет номер i-узла каталога уровнем выше, чем текущий.

Наряду с изученной ранее функцией open(...), которая позволяет как открывать, так и создавать файлы, в стандарте POSIX имеется функция mknod(...), обеспечивающая возможность создавать и различные специальные файлы.

Общий вызов функции следующий:

#include <sys/types.h>

#include <sys/stat.h>

#include <fcntl.h>

#include <unistd.h>

int mknod(const char *pathname, mode_t mode, dev_t dev);

где параметры функции определены как:

pathname — строковая константа, содержащая имя создаваемого файла;

mode — специфицирет параметры доступа и тип создаваемого узла (файла), причем тип может принимать следующие значения:

33

Рисунок 1.12 — Список файлов и их номеров i-узлов

S_IFREG=0 — соответствует обычному (регулярному) файлу;

S_IFCHR — соответствует симовольному устройству (специальный файл);

S_IFBLK — соответствует блочному устройству (специальный файл);

S_IFIFO — соответствует файлу типа FIFO (именованный канал);

S_IFSOCK — соответствует сокетам UNIX.

dev — используется только, когда определен S_IFCHR или S_IFBLK, тогда он задает старший и младший номера устройства.

Замечание

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

Класс устройства фактически сообвествует понятию тип устройства, определенному выше.

Старший номер устройства, группирует типы устройств, например, жесткий диск

34

или звуковая плата. Текущий список старших номеров устройств можно найти в файле /usr/include/linux/major.h. Небольшая выдержка из этого списка представлена в таблице 1.2.

Таблица 1.2 - Старшие номера некоторых устройств

Старший номер

Тип устройства

1

Оперативная память

 

 

2

Дисковод гибких дисков

3

Первый контроллер для жестких IDE-дисков

4

Терминалы

 

 

5

Терминалы

6

Принтер (параллельный разъем)

8

Жесткие SCSI-диски

 

 

14

Звуковые карты

22

Второй контроллер для жестких IDE-дисков

 

 

Старшие номера устройств, известных ядру, можно увидеть, выполнив команду:

cat /proc/devices

Файлы устройств одного типа имеют одинаковые имена и различаются по номеру, прибавляемому к имени. Например, все файлы сетевых плат Ethernet имеют имена, начинающиеся на eth: eth0, eth1 и другие.

Младший номер устройства применяется для нумерации устройств одного типа, другими словами, - устройств с одинаковыми старшими номерами.

Замечание

В ОС УПК АСУ создание и удаление специальных файлов устройств обеспечивается демоном systemd-udevd, поэтому эксперименты в этом направлении не поощря-ются.

1.4 Запрос информации о статусе файлов

Изучив основные особенности файлов, перейдем к рассмотрению системного вызова stat(...), который по заданному имени файла позволяет получить информацию о свойствах любых типов файлов.

Дополнительно, стандарт POSIX предоставляет функции:

fstat(...) - которая вместо имени файла использует номер его дескриптора;

35

lstat(...) - которая использует имя ссылки на файл и возвращяет информацию о самой ссылке, а не о файле, на который она ссылается.

Замечание

Работа со ссылками на файлы изложена в подразделе 1.8 данного руководства.

Общее описание перечисленных функций имеет следующий вид:

#include <sys/types.h>

#include <sys/stat.h>

#include <unistd.h>

int stat (const char *file_name, struct stat *buf); int fstat(int filedes, struct stat *buf); int lstat(const char *file_name, struct stat *buf);

Все эти функции возвращают структуру stat, которая содержит следующие поля:

struct stat {

 

 

dev_t

st_dev;

/* устройство */

ino_t

st_ino;

/* inode */

mode_t

st_mode;

/* режим доступа */

nlink_t

st_nlink;

/* количество жестких ссылок */

uid_t

st_uid;

/* идентификатор пользователя-владельца */

gid_t

st_gid;

/* идентификатор группы-владельца */

dev_t

st_rdev;

/* тип устройства */

 

 

/* (если это устройство) */

off_t

st_size;

/* общий размер в байтах */

blksize_t

st_blksize;

/* размер блока ввода-вывода */

 

 

/* в файловой системе */

blkcnt_t

st_blocks;

/* количество выделенных блоков */

time_t

st_atime;

/* время последнего доступа */

time_t

st_mtime;

/* время последней модификации */

time_t

st_ctime;

/* время последнего изменения */

};

 

 

Ряд полей этой структуры требует уточнения:

st_dev — описывает устройство, на котором находится этот файл; поскольку

это поле имеет тип dev_t, то для работы с ним необходимо пользоваться макросами major(…), miner(...) и mkdev(...), описанными ниже;

st_rdev - описывает устройство, которое представляет этот файл (inode);

st_size - задает размер файла в байтах, если он обычный или является сим-

вольной ссылкой; размер символьной ссылки - длина пути файла на который она сылается, без конечного NUL;

st_blocks - задает размер файла в 512-байтных блоках: оно может быть меньше, чем st_size/512, например, когда в файле есть пропуски;

st_blksize - задает "предпочтительный" размер блока для эффективного

ввода/вывода в файловой системе: запись в файл более мелкими порциями может привести к некорректному чтению/изменению/повторной записи информации;

Источник: https://studfile.net/preview/16438530/