Чтение онлайн

ЖАНРЫ

Разработка приложений в среде Linux. Второе издание

Троан Эрик В.

Шрифт:

11.2.8. Прочие операции

Файловая модель Linux достаточно хорошо поддерживает стандартизацию большинства файловых операций через обобщенные функции наподобие

read
и
write
(например, запись в программный канал выполняется так же, как запись в файл на диске). Однако некоторые устройства поддерживают операции, которые плохо моделируются такой абстракцией. Например, терминальные устройства, представленные как устройства символьные, нуждаются в представлении метода изменения скорости терминала, и приводы CD-ROM, представленные как блочные устройства, нуждаются в том, чтобы знать, кода они должны воспроизводить аудиодорожки, чтобы помочь увеличить производительность работы программистов.

Все эти разнообразные операции доступны через единственный системный вызов —

ioctl
(сокращение для "I/O control" — управление вводом-выводом), прототип которого показан ниже.

#include <sys/ioctl.h>

int ioctl(int fd, int request, ...);

Хотя

часто он применяется следующим образом:

int ioctl (int fd, int request, void *arg);

Всякий раз когда используется

ioctl
, его первый аргумент — это файл, с которым выполняются манипуляции, а второй аргумент указывает операцию, которая должна быть выполнена. Последний аргумент обычно представляет собой указатель на нечто, но на что именно, а так же точная семантика возвращаемого кода зависит от типа файла
fd
и типа запрошенной операции. Для некоторых операций
arg
— длинное целое вместо указателя; в этих случаях обычно применяется приведение типов. В нашей книге есть множество примеров применения
ioctl
, и вам нет нужды заботиться об
ioctl
до тех пор, пока вы не доберетесь до них.

11.3. Запрос и изменение информации inode

11.3.1. Поиск информации inode

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

open
, а не свойство самого файла). Linux предлагает три способа чтения информации inode.

#include <sys/stat.h>

int stat(const char *pathname, struct stat *statbuf);

int lstat (const char *pathname, struct stat *statbuf);

int fstat(int fd, struct stat *statbuf);

Первая версия,

stat
возвращает информацию
inode
для файла, на который осуществляется ссылка через
pathname
, следуя всем символическим ссылкам, которые она представляет. Если вы не хотите следовать символическим ссылкам (например, чтобы проверить, не является ли само имя такой ссылкой), то используйте вместо этого
lstat
. Последняя версия,
fstat
, возвращает
inode
, на который ссылается текущий открытый файловый дескриптор. Все три системных вызова заполняют структуру
struct stat
, на которую указывает параметр
statbuf
, информацией о файловом inode. В табл. 11.3 описана информация, доступная в
struct stat
.

Таблица 11.3. Члены структуры

struct stat

Тип Поле Описание
dev_t
st_dev
Номер устройства, на котором находится файл.
ino_t
st_ino
Номер файлового on-disk inode. Каждый файл имеет номер on-disk inode, уникальный в пределах устройства, на котором он расположен. То есть пара (
st_dev
,
st_ino
) представляет собой уникальный идентификатор файла.
mode_t
st mode
Режим файла. Сюда включена информация о правах доступа и типе файла.
nlink_t
st_nlink
Количество путевых имен, ссылающихся на данный inode. Сюда не включаются символические ссылки, потому что они ссылаются на другие имена, а не на inode.
uid_t
st_uid
Идентификатор пользователя, владеющего файлом.
gid_t
st_gid
Идентификатор группы, владеющей файлом.
dev_t
st_rdev
Если файл — символьное или блочное устройство, это задает старший (major) и младший (minor) номера файла. Чтобы получить информацию о членах и макросах, которые манипулируют этим значением, обратитесь к обсуждению mknod далее в этой главе.
off_t
st size
Размер
файла в байтах. Это определено только для обычных файлов.
unsigned long
st_blksize
Размер блока в файловой системе, хранящей файл.
unsigned long
st_blocks
Количество блоков, выделенных файлу. Обычно
st_blksize * st_blocks
— это немного больше, чем
st_size
, потому что некоторое пространство в конечном блоке не используется. Однако для файлов с "дырками"
st_blksize * st_blocks
может быть заметно меньше, чем
st_size
.
time_t
st_atime
Время последнего доступа к файлу. Обновляется при каждом открытии файла или модификации его inode.
time_t
st_mtime
Время последней модификации файла. Обновляется при изменении данных файла.
time_t
st_ctime
Последнее время изменения файла или его inode, включая владельца, группу, счетчик связей и так далее.

11.3.2. Простой пример

stat

Рассмотрим простую программу, которая отображает информацию из

lstat
для каждого имени файла, переданного в аргументе. Она иллюстрирует, как использовать значения, возвращенные семейством функций
stat
.

 1: /* statsamp.с */

 2:

 3: /* Для каждого имени файла, переданного в командной строке, отображаем

 4: всю информацию, которую возвращает lstat для файла. */

 5:

 6: #include <errno.h>

 7: #include <stdio.h>

 8: #include <string.h>

 9: #include <sys/stat.h>

10: #include <sys/sysmacros.h>

11: #include <sys/types.h>

12: #include <time.h>

13: #include <unistd.h>

14:

15: #define TIME_STRING_BUF 50

16:

17: /* Пользователь передает buf (минимальной длины TIME_STRING_BUF) вместо

18: использования статического для функции буфера, чтобы избежать применения

19: локальных статических переменных и динамической памяти. Никаких ошибок

20: происходить не должно, поэтому никакой проверки ошибок не делаем. */

21: char *time String (time_t t, char *buf) {

22: struct tm *local;

23:

24: local = localtime(&t);

25: strftime(buf, TIME_STRING_BUF, "%c", local);

26:

27: return buf;

28: }

29:

30: /* Отобразить всю информацию, полученную от lstat по имени

31: файла как единственному параметру. */

32: int statFile(const char *file) {

33: struct stat statbuf;

34: char timeBuf[TIME_STRING_BUF];

35:

36: if (lstat(file, &statbuf)) {

37: fprintf(stderr, "не удалось lstat %s: %s\n", file,

38: strerror(errno));

39: return 1;

40: }

41:

42: printf("Имя файла : %s\n", file);

43: printf("На устройстве: старший %d/младший %d Inode номер: %ld\n" ,

44: major(statbuf.st_dev), minor(statbuf.st_dev),

45: statbuf.st_ino);

46: printf ("Размер : %-101d Тип: %07o"

47: "Права доступа : %05o\n", statbuf.st_size,

48: statbuf.st_mode & S_IFMT, statbuf.st_mode &~(S_IFMT));

49: printf("Владелец : %d Группа : %d"

50: " Количество ссылок : %d\n",

51: statbuf.st_uid, statbuf.st_gid, statbuf.st_nlink);

52: printf("Время создания : %s\n",

Поделиться с друзьями: