stat () - это системный вызов Unix , возвращает атрибуты файла для inode. Семантика stat () различается в зависимости от операционных систем. Например, Unix команда ls использует этот системный вызов для получения информации о файлах, которая включает:
stat
появилось в Версия 1 Unix. Это один из немногих исходных системных вызовов Unix , которые необходимо изменить, с добавлением в версии 4 групповых разрешений и более крупных размер файла.
Библиотека C POSIX заголовок sys / stat.h, найденный в POSIX и других Unix-подобных, объявляет функции stat ()
, а также связанные с ними функции, называемые fstat ()
и lstat ()
. Функции принимают аргумент буфера структуры struct stat
, который используется для возврата атрибутов файла. В случае успеха функции возвращают ноль, а в случае ошибки возвращается -1, а значение errno устанавливается соответствующим образом.
Функции stat ()
и lstat ()
принимают аргумент filename. Если файл представляет собой символическую ссылку , stat ()
возвращает атрибуты конечной цели ссылки, а lstat ()
возвращает атрибуты самой ссылки. Функция fstat ()
вместо этого принимает аргумент дескриптора файла и возвращает атрибуты файла, который она идентифицирует.
Семейство функций было расширено для реализации поддержки больших файлов. Функции с именами stat64 ()
, lstat64 ()
и fstat64 ()
возвращают атрибуты в структуре struct stat64
, которая представляет размеры файлов с 64-битный тип, позволяющий функциям работать с файлами размером 2 ГиБ и более (до 8 ЭиБ). Если для макроса _FILE_OFFSET_BITS
задано значение 64, эти 64-битные функции доступны под исходными именами.
Функции определены как:
int stat (const char * filename, struct stat * buf); int lstat (const char * filename, struct stat * buf); int fstat (int filedesc, struct stat * buf);
Эта структура определена в заголовочном файле sys / stat.h следующим образом, хотя реализации могут определять дополнительные поля:
struct stat {mode_t st_mode; ino_t st_ino; dev_t st_dev; dev_t st_rdev; nlink_t st_nlink; uid_t st_uid; gid_t st_gid; off_t st_size; struct timespec st_atim; struct timespec st_mtim; struct timespec st_ctim; blksize_t st_blksize; blkcnt_t st_blocks; };
POSIX.1 не требует элементов st_rdev
, st_blocks
и st_blksize
; эти поля определены как часть опции XSI в Single Unix Specification.
В более старых версиях стандарта POSIX.1 поля, связанные со временем, были определены как st_atime
, st_mtime
и st_ctime
и имели введите time_t
. Начиная с версии стандарта 2008 года, эти поля были переименованы в st_atim
, st_mtim
и st_ctim
, соответственно, типа struct timespec
, поскольку эта структура обеспечивает единицу времени с более высоким разрешением. Для совместимости реализации могут определять старые имена в терминах элемента tv_sec
структуры struct timespec
. Например, st_atime
можно определить как st_atim.tv_sec
.
Структура struct stat
включает как минимум следующие элементы:
st_dev
- идентификатор устройство, содержащее файлst_ino
- номер inode st_mode
- режим защиты ; см. также разрешения Unix st_nlink
- количество ссылок из жестких ссылок st_uid
- идентификатор пользователя владельцаst_gid
- идентификатор группы владельцаst_rdev
- идентификатор устройства (если специальный файл )st_size
- общий размер файла, в байтахst_atime
- время последнего доступаst_mtime
- время последней модификацииst_ctime
- время последнего изменения статусаst_blksize
- предпочтительно размер блока для ввода-вывода файловой системы, который может зависеть как от системы, так и от типа файловой системыst_blocks
- количество блоков, выделенных кратно DEV_BSIZE
(обычно 512 байт).Поле st_mode
является битовым полем . Оно объединяет режимы доступа к файлам , а также указывает любой специальный тип файла. Существует множество макросов для работы с различными флагами режима и типами файлов.
Чтение файла изменяет его время, в конечном итоге требующее записи на диск, что имеет был криком ticized, так как он несовместим с файловой системой только для чтения. Кэш файловой системы может значительно сократить эту активность до одной записи на диск за очистку кеша.
Ядро Linux разработчик Инго Мольнар публично раскритиковал концепцию и влияние atime на производительность в 2007 году, а в 2009 году опция монтирования relatime стала по умолчанию, что устраняет эту критику. Поведение, стоящее за опцией монтирования relatime, обеспечивает достаточную производительность для большинства целей и не должно нарушать работу каких-либо значительных приложений, поскольку это подробно обсуждалось. Изначально relatime обновлял atime только в том случае, если atime < mtime or atime < ctime; that was subsequently modified to update atimes that were 24 hours old or older, so that tmpwatch и счетчик популярности Debian (popcon) будут вести себя правильно.
Текущие версии ядра Linux поддерживают четыре варианта монтирования, которые можно указать в fstab :
Текущие версии Linux, macOS, Solaris, FreeBSD и NetBSD поддерживают опцию монтирования noatime в / etc / fstab, из-за которой поле atime никогда не обновляется. Отключение времени обновления нарушает соответствие POSIX и некоторые приложения, такие как t_dv -driven уведомления о "новой почте ", а также некоторые служебные программы для отслеживания использования файлов, в частности.
Параметр noatime в OpenBSD ведет себя больше как Linux relatime.
Версия 4.0 основной ветки ядра Linux , которая был выпущен 12 апреля 2015 года, в нем была представлена новая опция монтирования lazytime. Он позволяет выполнять обновления времени в стиле POSIX в памяти и сбрасывать на диск вместе с некоторыми операциями ввода-вывода, не связанными со временем, в том же файле; Временные обновления также сбрасываются на диск при выполнении некоторых системных вызовов sync или до того, как индексный дескриптор файла в памяти будет удален из кеша файловой системы. Кроме того, можно настроить, как долго изменения могут оставаться не сброшенными. Таким образом, lazytime сохраняет совместимость с POSIX, предлагая при этом улучшения производительности.
Заманчиво полагать, что изначально означало время создания; однако, в то время как ранние версии Unix имели время модификации и создания, последнее было изменено на время доступа до того, как появилась какая-либо структура C, в которой можно было бы вызывать что-либо ctime. Файловые системы сохранили только время доступа (atime) и время модификации (mtime) до 6-го издания Unix. Временная метка ctime была добавлена при реструктуризации файловой системы, которая произошла в 7-й редакции Unix, и всегда относилась ко времени изменения inode. Он обновляется каждый раз при изменении метаданных файла, хранящихся в индексном дескрипторе, таких как права доступа к файлу, право собственности на файл и создание и удаление жестких ссылок. В некоторых реализациях на ctime влияет переименование файла: как в оригинальном Unix, в котором было реализовано переименование, создавая ссылку (обновляя ctime), а затем отключая старое имя (снова обновляя ctime)), так и в современном. Linux имеет тенденцию делать это.
В отличие от atime и mtime, для ctime нельзя установить произвольное значение с помощью utime (), как используется touch утилита, например. Вместо этого, когда используется utime () или для любого другого изменения inode, кроме обновления до atime, вызванного доступом к файлу, значение ctime устанавливается на текущее время.
#include#include #include #include #include #include # включить int main (int argc, char * argv) {struct stat sb; struct passwd * pwuser; struct group * grpnam; если (argc < 2) { fprintf(stderr, "Usage: %s: file...\n", argv[0]); exit(EXIT_FAILURE); } for (int i = 1; i < argc; i++) { if (-1 == stat(argv[i], sb)) { perror("stat()"); exit(EXIT_FAILURE); } if (NULL == (pwuser = getpwuid(sb.st_uid))) { perror("getpwuid()"); exit(EXIT_FAILURE); } if (NULL == (grpnam = getgrgid(sb.st_gid))) { perror("getgrgid()"); exit(EXIT_FAILURE); } printf("%s:\n", argv[i]); printf("\tinode: %u\n", sb.st_ino); printf("\towner: %u (%s)\n", sb.st_uid, pwuser->pw_name); printf ("\ tgroup:% u (% s) \ n", sb.st_gid, grpnam->gr_name); printf ("\ tperms:% o \ n", sb.st_mode (S_IRWXU | S_IRWXG | S_IRWXO)); printf ("\ tlinks:% d \ n", sb.st_nlink); printf ("\ tsize:% ld \ n", sb.st_size); / * вы можете использовать% lld * / printf ("\ tatime:% s", ctime (sb.st_atim.tv_sec)); printf ("\ tmtime:% s", ctime (sb.st_mtim.tv_sec)); printf ("\ tctime:% s", ctime (sb.st_ctim.tv_sec)); printf ("\ п"); } return 0; }