стат (системный вызов)
stat() — это Unix системный вызов , который возвращает атрибуты файла для индексного дескриптора . Семантика stat() различаются в зависимости от операционной системы . Например, Unix команда ls использует этот системный вызов для получения информации о файлах, которая включает в себя:
- atime: время последнего доступа ( лс -лу )
- mtime: время последней модификации ( лс -л )
- ctime: время последнего изменения статуса ( лс -лк )
stat
появился в версии 1 Unix . Это один из немногих исходных системных вызовов Unix , которые необходимо изменить: в версии 4 были добавлены групповые разрешения и увеличен размер файла . [1]
функции стат()
[ редактировать ]Заголовок POSIX библиотеки C sys/stat.h , найденный в POSIX и других Unix-подобных операционных системах, объявляет stat()
функции, а также связанные с ними функции, называемые fstat()
и lstat()
. Функции принимают указатель на struct stat
Аргумент буфера, который используется для возврата атрибутов файла. В случае успеха функции возвращают ноль, а в случае ошибки возвращается −1, и errno устанавливается соответствующим образом.
The stat()
и lstat()
функции принимают аргумент имени файла . Если файл является символической ссылкой , stat()
возвращает атрибуты конечной цели ссылки, а lstat()
возвращает атрибуты самой ссылки. fstat()
Вместо этого функция принимает аргумент дескриптора файла и возвращает атрибуты файла, который она идентифицирует.
Семейство функций было расширено для реализации поддержки больших файлов . Функции с именем stat64()
, lstat64()
и fstat64()
возвращать атрибуты в struct stat64
структура, которая представляет размеры файлов 64-битного типа, что позволяет функциям работать с файлами размером 2 ГиБ и больше (до 8 EiB). Когда _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 следующим образом, хотя реализации могут определять дополнительные поля: [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 в Единой спецификации 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]
The 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 байт).
The st_mode
поле представляет собой битовое поле . Он объединяет режимы доступа к файлам , а также указывает любой специальный тип файла . Существует множество макросов для работы с различными флагами режимов и типами файлов.
Критика времени
[ редактировать ]В этом разделе может быть придан чрезмерный вес определенным идеям, происшествиям или противоречиям . Пожалуйста, помогите создать более сбалансированную презентацию . Обсудите и решите эту проблему, прежде чем удалять это сообщение. ( март 2015 г. ) |
Чтение файла меняет его atime в конечном итоге требует записи на диск, что подвергается критике, поскольку оно несовместимо с файловой системой только для чтения. Кэш файловой системы может значительно сократить эту активность до одной записи на диск на одну очистку кэша.
ядра Linux Разработчик Инго Молнар публично раскритиковал концепцию и влияние atime на производительность в 2007 году. [4] [5] и в 2009 году relatime Опция монтирования стала значением по умолчанию, что устраняет эту критику. [6] Поведение, лежащее в основе Опция монтирования relatime обеспечивает достаточную производительность для большинства целей и не должна нарушать работу каких-либо важных приложений, как это широко обсуждалось. [7] Изначально, relatime обновляет atime только в том случае, если atime < mtime или atime < ctime; который впоследствии был изменен для обновления времени, которое было 24 часа назад или старше, так что tmpwatch и счетчик популярности Debian (popcon) будут вести себя правильно. [8]
Текущие версии ядра Linux поддерживают четыре варианта монтирования, которые можно указать в fstab :
- строгое время (ранее atime , ранее значение по умолчанию; strictatime с версии 2.6.30) — всегда обновлять время, соответствующее поведению, определенному POSIX.
- relatime («относительное время», введенное в версии 2.6.20 и значение по умолчанию с версии 2.6.30) — обновлять время только при определенных обстоятельствах: если предыдущее время старше, чем mtime или ctime, или предыдущее время превышает 24 часа в прошлое
- nodiratime – никогда не обновлять время каталогов, но обновлять время других файлов
- noatime – никогда не обновлять время любого файла или каталога; подразумевает нодиратиме ; высочайшая производительность, но наименее совместимость
- lazytime – обновлять время в соответствии с конкретными обстоятельствами, изложенными ниже.
Текущие версии Linux , macOS , Solaris , FreeBSD и NetBSD поддерживают опция монтирования noatime в /etc/fstab , из-за которой поле atime никогда не обновляется. Отключение обновления времени нарушает соответствие POSIX , а некоторые приложения, такие как », управляемые mbox уведомления о «новой почте , [9] и некоторые утилиты для наблюдения за использованием файлов, в частности tmpwatch .
The опция noatime в OpenBSD больше похожа на Linux относительное время . [10]
В версии 4.0 основной ветки ядра Linux , выпущенной 12 апреля 2015 года, появилась новая опция монтирования. ленивое время . Он позволяет выполнять обновления atime в стиле POSIX в памяти и сбрасывать их на диск вместе с некоторыми не связанными со временем операциями ввода-вывода в том же файле; Обновления atime также сбрасываются на диск при выполнении некоторых системных вызовов синхронизации или перед удалением индексного дескриптора файла из кэша файловой системы. Кроме того, можно настроить, как долго изменения могут оставаться несброшенными. Таким образом, lazytime сохраняет совместимость с POSIX, одновременно обеспечивая повышение производительности. [11] [12]
ctime
[ редактировать ]Заманчиво поверить, что ctime первоначально означало время создания; [13] однако, хотя в ранних версиях Unix действительно было время модификации и создания, последнее было изменено на время доступа до того, как появилась какая-либо структура C, в которой можно было что-либо вызвать. время . Файловые системы сохраняли только время доступа ( atime ) и время модификации ( mtime ) до 6-й редакции Unix. Временная метка ctime была добавлена при реструктуризации файловой системы, которая произошла в версии 7 Unix , и всегда относилась ко времени смены индексного дескриптора. Он обновляется каждый раз, когда изменяются метаданные файла, хранящиеся в индексном дескрипторе, такие как права доступа к файлу , владение файлом , а также создание и удаление жестких ссылок . POSIX также требует обновление ctime (последнее изменение статуса) с ненулевым значением write() (модификация файла). [14] В некоторых реализациях На ctime влияет переименование файла, несмотря на то, что имена файлов не сохраняются в индексных дескрипторах. ctime ), а затем отсоединить старое имя (обновив ctime снова), и современный Linux склонен делать это.
В отличие от время и время , ctime не может быть установлено произвольное значение с помощью utime() , используемый Touch , например. Вместо этого, когда utime() или для любого другого изменения индексного дескриптора, кроме обновления время, вызванное доступ к файлу, Значение ctime установлено на текущее время.
Детализация времени
[ редактировать ]- time_t предоставляет время с точностью до одной секунды.
- Некоторые файловые системы обеспечивают более тонкую детализацию. Solaris 2.1 представил микросекундное разрешение с UFS в 1992 году. [ нужна ссылка ] и наносекундное разрешение с ZFS. [ нужна ссылка ]
- В ядрах Linux версии 2.5.48 и выше структура stat поддерживает наносекундное разрешение для трех полей меток времени файла. Они отображаются как дополнительные поля в структуре статистики. [15] [16]
- Разрешение времени создания в файловой системе FAT составляет 10 миллисекунд, разрешение времени записи — две секунды, а время доступа имеет разрешение один день, поэтому оно действует как дата доступа. [17]
Пример
[ редактировать ]Этот раздел может сбивать с толку или быть неясным для читателей . ( январь 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;
if (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); /* you may use %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("\n");
}
return 0;
}
Ссылки
[ редактировать ]- ^ Макилрой, доктор медицины (1987). Читатель Research Unix: аннотированные выдержки из Руководства программиста, 1971–1986 (PDF) (Технический отчет). CSTR. Лаборатории Белла. 139.
- ^ Перейти обратно: а б Стивенс и Раго, 2013 , с. 94.
- ^ "<sys/stat.h>" . Базовые спецификации открытой группы, выпуск 6 — стандарт IEEE 1003.1, издание 2004 г. Открытая группа. 2004.
- ^ Ловушка ядра: Linux: замена atime на relatime , Джереми, 7 августа 2007 г.
- ↑ Однажды , LWN, Джонатан Корбет, 8 августа 2007 г.
- ^ Ядро Linux 2.6.30 , Новички в ядре Linux
- ^ Эта огромная тема о файловой системе , LWN, Джонатан Корбет, 31 марта 2009 г.
- ^ Резюме Relatime , Валери Аврора
- ^ http://www.mail-archive.com/ [email protected] /msg24912.html "Монитор оболочки $MAIL... зависит от atime, произнося новое электронное письмо с помощью atime($MAIL) < mtime($MAIL)"
- ^ «mount(2) — страницы руководства OpenBSD» . openbsd.org . 27 апреля 2018 года . Проверено 26 сентября 2018 г.
- ^ «Ядро Linux 4.0, раздел 1.5. Опция lazytime для лучшего обновления временных меток файлов» . kernelnewbies.org . 1 мая 2015 года . Проверено 2 мая 2015 г.
- ^ Джонатан Корбет (19 ноября 2014 г.). «Представляем ленивое время» . LWN.net . Проверено 2 мая 2015 г.
- ^ «Версия BSTJ документа C.ACM Unix» .
- ^ «писать, писать — писать в файл» .
После успешного завершения, если nbyte больше 0, write() помечает для обновления метки времени последней модификации данных и последнего изменения статуса файла.
- ^ «stat(2) — страница руководства Linux» . man7.org . Проверено 27 февраля 2015 г.
- ^ Андреас Йегер (2 декабря 2002 г.), структура stat.h с наносекундным разрешением , почтовый архив списка рассылки [email protected] для проекта glibc.
- ^ MSDN: Время файлов
- IEEE Std 1003.1, 2004 г., документация для fstat(2) . Проверено 7 июня 2012 г.
- stat(2) Справочная страница Linux . Проверено 7 июня 2012 г.
- Стивенс, В. Ричард; Раго, Стивен А. (24 мая 2013 г.). Расширенное программирование в среде UNIX (Третье изд.). Аддисон-Уэсли Профессионал . ISBN 978-0321637734 . Проверено 27 февраля 2015 г.