stat() — это системный вызов Unix , который возвращает атрибуты файла об inode . Семантика stat() различается в зависимости от операционной системы . Например,команда Unix ls использует этот системный вызов для получения информации о файлах, которая включает:
stat
появился в версии 1 Unix . Это один из немногих оригинальных системных вызовов Unix , который был изменен, с добавлением в версии 4 групповых разрешений и большего размера файла . [1]
Заголовок библиотеки C POSIX sys/stat.h , который можно найти в POSIX и других Unix-подобных операционных системах, объявляет функции, а также связанные функции, называемые и . Функции принимают указатель на аргумент буфера, который используется для возврата атрибутов файла. При успешном выполнении функции возвращают ноль, а при ошибке возвращается −1 и errno устанавливается соответствующим образом.stat()
fstat()
lstat()
struct stat
Функции stat()
и lstat()
принимают аргумент имени файла . Если файл является символической ссылкой , stat()
возвращает атрибуты конечной цели ссылки, тогда как lstat()
возвращает атрибуты самой ссылки. fstat()
Функция принимает вместо этого аргумент дескриптора файла и возвращает атрибуты файла, который он идентифицирует.
Семейство функций было расширено для реализации поддержки больших файлов . Функции с именами stat64()
и возвращают атрибуты в структуре, которая представляет размеры файлов с 64-битным типом, что позволяет функциям работать с файлами размером 2 ГиБ и больше (до 8 ЭиБ). Когда макрос lstat64()
определен как 64, эти 64-битные функции доступны под исходными именами.fstat64()
struct stat64
_FILE_OFFSET_BITS
Функции определяются как:
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 следующим образом, хотя реализации могут свободно определять дополнительные поля: [2]
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.
В более старых версиях стандарта 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
. [2]
В состав struct stat
входят как минимум следующие члены:
st_dev
– идентификатор устройства, содержащего файлst_ino
– номер инодаst_mode
– режим защиты ; см. также разрешения Unixst_nlink
– количество ссылок на жесткие ссылкиst_uid
– идентификатор пользователя владельцаst_gid
– групповой идентификатор владельцаst_rdev
– идентификатор устройства (если специальный файл )st_size
– общий размер файла , в байтахst_atime
– время последнего доступаst_mtime
– время последней модификацииst_ctime
– время последнего изменения статусаst_blksize
– предпочтительный размер блока для ввода-вывода файловой системы, который может зависеть как от системы, так и от типа файловой системы [3]st_blocks
– количество выделенных блоков, кратное DEV_BSIZE
(обычно 512 байт).Поле st_mode
представляет собой битовое поле . Оно объединяет режимы доступа к файлам , а также указывает на любой специальный тип файла . Существует множество макросов для работы с различными флагами режимов и типами файлов.
Этот раздел может придать ненужный вес определенным идеям, инцидентам или противоречиям . Пожалуйста, помогите создать более сбалансированную презентацию . Обсудите и решите эту проблему, прежде чем удалять это сообщение. ( март 2015 г. ) |
Чтение файла изменяет его время , в конечном итоге требуя записи на диск, что подвергалось критике, поскольку несовместимо с файловой системой только для чтения. Кэш файловой системы может значительно сократить эту активность до одной записи на диск на очистку кэша.
Разработчик ядра Linux Инго Молнар публично раскритиковал концепцию и влияние atime на производительность в 2007 году, [4] [5] а в 2009 году опция монтирования relatime стала опцией по умолчанию, что решает эту критику. [6] Поведение, лежащее в основе опции монтирования relatime , обеспечивает достаточную производительность для большинства целей и не должно нарушать работу каких-либо важных приложений, поскольку это широко обсуждалось. [7] Первоначально relatime обновлял atime только если atime < mtime или atime < ctime; впоследствии это было изменено для обновления atime, которые были старше 24 часов, так что tmpwatch и счетчик популярности Debian (popcon) работали правильно. [8]
Текущие версии ядра Linux поддерживают четыре параметра монтирования, которые можно указать в fstab :
Текущие версии Linux , macOS , Solaris , FreeBSD и NetBSD поддерживают опцию монтирования noatime в /etc/fstab , которая заставляет поле atime никогда не обновляться. Отключение обновления atime нарушает соответствие POSIX , и некоторые приложения, такие как уведомления о "новой почте ", управляемые mbox [9], и некоторые утилиты для отслеживания использования файлов, в частности tmpwatch.
Опция noatime в OpenBSD ведет себя скорее как relatime в Linux . [10]
Версия 4.0 основной ветки ядра Linux , выпущенная 12 апреля 2015 года, представила новую опцию монтирования lazytime . Она позволяет выполнять обновления atime в стиле POSIX в памяти и сбрасывать их на диск вместе с некоторыми не связанными со временем операциями ввода-вывода в том же файле; обновления atime также сбрасываются на диск, когда выполняются некоторые системные вызовы синхронизации или до того, как inode файла в памяти будет вытеснен из кэша файловой системы. Кроме того, можно настроить, как долго изменения atime могут оставаться несброшенными. Таким образом, lazytime сохраняет совместимость с POSIX, предлагая улучшения производительности. [11] [12]
Возникает соблазн поверить, что ctime изначально означало время создания; [13] однако, хотя в ранних версиях Unix были времена изменения и создания, последнее было изменено на время доступа до того, как появилась какая-либо структура C, в которой можно было бы что-либо назвать ctime . Файловые системы сохранили только время доступа ( atime ) и время изменения ( mtime ) вплоть до 6-го издания Unix. Временная метка ctime была добавлена в ходе реструктуризации файловой системы, которая произошла с версией 7 Unix , и всегда относилась к времени изменения inode. Она обновляется каждый раз, когда изменяются метаданные файла, хранящиеся в inode, такие как разрешения файла , владение файлом и создание и удаление жестких ссылок . POSIX также требует обновления ctime (последнее изменение статуса) с ненулевым write() (изменение файла). [14] В некоторых реализациях на ctime влияет переименование файла, несмотря на то, что имена файлов не хранятся в inode: как оригинальный Unix, который реализовал переименование путем создания ссылки (обновления ctime ) и последующего удаления ссылки на старое имя (повторного обновления ctime ), так и современный Linux, как правило, делают это.
В отличие от atime и mtime , ctime не может быть установлено в произвольное значение с помощью utime() , как это используется , например, утилитой touch . Вместо этого, когда используется utime() или для любого другого изменения inode, отличного от обновления atime, вызванного доступом к файлу, значение ctime устанавливается в текущее время.
Этот раздел может быть запутанным или неясным для читателей . ( Январь 2023 г. ) |
#include <stdio.h> #include <stdlib.h> #include <time.h> #include <sys/types.h> #include <pwd.h> #include <grp.h> #include <sys/stat.h> int main ( int argc , char * argv []) { struct stat sb ; struct passwd * pwuser ; struct group * grpnam ; если ( argc < 2 ) { fprintf ( stderr , "Использование: %s: файл ... \n " , argv [ 0 ]); выход ( EXIT_FAILURE ); } для ( int i = 1 ; i < argc ; i ++ ) { если ( -1 == stat ( argv [ i ], & sb )) { perror ( "stat()" ); выход ( EXIT_FAILURE ); } если ( NULL == ( pwuser = getpwuid ( sb . st_uid ))) { perror ( "getpwuid()" ); выход ( EXIT_FAILURE ); } если ( NULL == ( grpnam = getgrgid ( sb . st_gid ))) { perror ( "getgrgid()" ); выход ( EXIT_FAILURE ); } printf ( "%s: \n " , argv [ i ]); printf ( " \t inode : %u \ n " , sb.st_ino ); printf ( " \t владелец: %u (%s) \n " , sb.st_uid , pwuser - > pw_name ); printf ( " \t группа : %u (%s) \ n " , sb.st_gid , grpnam - > gr_name ); printf ( " \t права: %o \n " , sb.st_mode & ( S_IRWXU | S_IRWXG | S_IRWXO )); printf ( " \ t ссылки: %d \ n " , sb.st_nlink ) ; printf ( " \t размер: % ld \ n " , sb.st_size ) ; /* вы можете использовать % lld */ printf ( " \t atime: %s" , ctime ( & sb.st_atim.tv_sec ) ) ; printf ( " \ t mtime: %s" , ctime ( & sb.st_mtim.tv_sec ) ) ; printf ( " \ t ctime : % s" , ctime ( & sb.st_ctim.tv_sec ) ) ; printf ( " \n " ); }вернуть 0 ; }
После успешного завершения, где nbyte больше 0, write() помечает для обновления последние изменения данных и последние временные метки изменения статуса файла