stat (системный вызов)

Системный вызов Unix

statкомандная строка

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

  • atime: время последнего доступа ( ls -lu )
  • mtime: время последней модификации ( ls -l )
  • ctime: время последнего изменения статуса ( ls -lc )

statпоявился в версии 1 Unix . Это один из немногих оригинальных системных вызовов Unix , который был изменен, с добавлением в версии 4 групповых разрешений и большего размера файла . [1]

stat() функции

Заголовок библиотеки 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_modeпредставляет собой битовое поле . Оно объединяет режимы доступа к файлам , а также указывает на любой специальный тип файла . Существует множество макросов для работы с различными флагами режимов и типами файлов.

Критика времени

Чтение файла изменяет его время , в конечном итоге требуя записи на диск, что подвергалось критике, поскольку несовместимо с файловой системой только для чтения. Кэш файловой системы может значительно сократить эту активность до одной записи на диск на очистку кэша.

Разработчик ядра Linux Инго Молнар публично раскритиковал концепцию и влияние atime на производительность в 2007 году, [4] [5] а в 2009 году опция монтирования relatime стала опцией по умолчанию, что решает эту критику. [6] Поведение, лежащее в основе опции монтирования relatime , обеспечивает достаточную производительность для большинства целей и не должно нарушать работу каких-либо важных приложений, поскольку это широко обсуждалось. [7] Первоначально relatime обновлял atime только если atime < mtime или atime < ctime; впоследствии это было изменено для обновления atime, которые были старше 24 часов, так что tmpwatch и счетчик популярности Debian (popcon) работали правильно. [8]

Текущие версии ядра Linux поддерживают четыре параметра монтирования, которые можно указать в fstab :

  • strictatime (ранее atime и ранее значение по умолчанию; strictatime с версии 2.6.30) — всегда обновлять atime, что соответствует поведению, определенному POSIX
  • relatime («относительное atime», введено в 2.6.20 и используется по умолчанию с 2.6.30) — обновляет atime только при определенных обстоятельствах: если предыдущее atime старше mtime или ctime, или предыдущее atime прошло более 24 часов
  • nodiratime  – никогда не обновлять atime каталогов, но обновлять atime других файлов
  • noatime  – никогда не обновлять atime любого файла или каталога; подразумевает nodiratime ; самая высокая производительность, но самая низкая совместимость
  • lazytime  – обновляйте atime в соответствии с конкретными обстоятельствами, изложенными ниже

Текущие версии 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

Возникает соблазн поверить, что 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 устанавливается в текущее время.

Детализация времени

  • time_t предоставляет время с точностью до одной секунды.
  • Некоторые файловые системы обеспечивают более тонкую гранулярность. Solaris 2.1 ввел микросекундное разрешение с UFS в 1992 году [ требуется цитата ] и наносекундное разрешение с ZFS. [ требуется цитата ]
  • В ядрах Linux 2.5.48 и выше структура stat поддерживает наносекундное разрешение для трех полей временной метки файла. Они представлены как дополнительные поля в структуре stat. [15] [16]
  • Разрешение времени создания в файловой системе FAT составляет 10 миллисекунд, в то время как разрешение времени записи составляет две секунды, а время доступа имеет разрешение в один день, поэтому оно действует как дата доступа. [17]

Пример

#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 ; } 

Ссылки

  1. ^ Макилрой, МД (1987). Исследовательский ридер Unix: аннотированные выдержки из Руководства программиста, 1971–1986 (PDF) (Технический отчет). CSTR. Bell Labs. 139.
  2. ^ Стивенс и Раго 2013, стр. 94.
  3. ^ "<sys/stat.h>". Базовые спецификации Open Group, выпуск 6 — IEEE Std 1003.1, издание 2004 г. The Open Group. 2004.
  4. ^ Kernel Trap: Linux: Замена atime на relatime, Джереми, 7 августа 2007 г.
  5. Однажды в сказке, LWN, Джонатан Корбет, 8 августа 2007 г.
  6. ^ Ядро Linux 2.6.30, Новички в ядре Linux
  7. ^ Огромная тема файловой системы, LWN, Джонатан Корбет, 31 марта 2009 г.
  8. ^ Relatime Recap, Валери Аврора
  9. ^ http://www.mail-archive.com/mutt-users@mutt.org/msg24912.html "монитор $MAIL оболочки ... зависит от atime, произнося новое письмо как atime($MAIL) < mtime($MAIL)"
  10. ^ "mount(2) - Страницы руководства OpenBSD". openbsd.org . 27 апреля 2018 г. . Получено 26 сентября 2018 г. .
  11. ^ "Linux kernel 4.0, раздел 1.5. опция 'lazytime' для лучшего обновления временных меток файлов". kernelnewbies.org . 1 мая 2015 г. . Получено 2 мая 2015 г. .
  12. Джонатан Корбет (19 ноября 2014 г.). «Введение в lazytime». LWN.net . Получено 2 мая 2015 г.
  13. ^ "BSTJ-версия статьи C.ACM Unix".
  14. ^ "pwrite, write - запись в файл". После успешного завершения, где nbyte больше 0, write() помечает для обновления последние изменения данных и последние временные метки изменения статуса файла
  15. ^ "stat(2) - Страница руководства Linux". man7.org . Получено 27 февраля 2015 г. .
  16. Андреас Йегер (2 декабря 2002 г.), struct stat.h с наносекундным разрешением, почтовый архив списка рассылки libc-alpha@sources.redhat.com для проекта glibc.
  17. ^ MSDN: Время файла
  • IEEE Std 1003.1, 2004, документация для fstat(2). Получено 2012-06-07.
  • stat(2) Страница руководства Linux. Получено 2012-06-07.
  • Стивенс, В. Ричард; Раго, Стивен А. (24 мая 2013 г.). Advanced Programming in the UNIX Environment (Третье изд.). Addison-Wesley Professional . ISBN 978-0321637734. Получено 27 февраля 2015 г. .
  • Пример, показывающий, как использовать stat() Архивировано 11 мая 2017 г. на Wayback Machine
  • stat() в Perl
  • stat() в PHP
  • время и время относительно
Получено с "https://en.wikipedia.org/w/index.php?title=Stat_(system_call)&oldid=1224930310"