stat (wywołanie systemowe) - stat (system call)

stat wiersz poleceń

stat() to uniksowe wywołanie systemowe, które zwraca atrybuty pliku dotyczące i- węzła . Semantyka stat() różni się w zależności od systemu operacyjnego . Na przykładpolecenie uniksowe ls używa tego wywołania systemowego do pobierania informacji o plikach, które obejmują:

  • atime: czas ostatniego dostępu ( ls -lu )
  • mtime: czas ostatniej modyfikacji ( ls -l )
  • ctime: czas ostatniej zmiany statusu ( ls -lc )

statpojawił się w wersji 1 Unix . Jest jednym z niewielu oryginalny Unix wywołań systemowych do zmiany z wersji 4 oprócz „s z uprawnieniami grupy oraz większego rozmiaru pliku .

funkcje stat()

Biblioteka C POSIX nagłówek sys / stat.h , znalezionych na POSIX oraz innych uniksowych systemach operacyjnych, deklaruje stat()funkcje, a także związane z nimi funkcje zwane fstat()oraz lstat(). Funkcje przyjmują struct statargument bufora, który jest używany do zwracania atrybutów pliku. W przypadku powodzenia funkcje zwracają zero, a w przypadku błędu zwracane jest −1 i odpowiednio ustawiane errno .

Funkcje stat()i lstat()przyjmują argument nazwy pliku . Jeśli plik jest dowiązaniem symbolicznym , stat()zwraca atrybuty ostatecznego celu dowiązania, podczas gdy lstat()zwraca atrybuty samego dowiązania. fstat()Funkcja przyjmuje deskryptora pliku argumentu zamiast i powraca atrybuty pliku, który go identyfikuje.

Rodzina funkcji została rozszerzona w celu implementacji obsługi dużych plików . Funkcje nazwane stat64(), lstat64()i fstat64()atrybuty powrotny w struct stat64strukturze, która reprezentuje rozmiary plików z typem 64-bitowej, dzięki czemu funkcje do pracy na plikach 2 Gib i większe (do 8 EBI). Gdy _FILE_OFFSET_BITS makro jest zdefiniowane jako 64, te 64-bitowe funkcje są dostępne pod oryginalnymi nazwami.

Funkcje są zdefiniowane jako:

int stat(const char *filename, struct stat *buf);
int lstat(const char *filename, struct stat *buf);
int fstat(int filedesc, struct stat *buf);

struktura statystyk

Struktura ta jest zdefiniowana w pliku nagłówkowym sys/stat.h w następujący sposób, chociaż implementacje mogą dowolnie definiować dodatkowe pola:

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 nie wymaga st_rdev, st_blocksi st_blksizeczłonków; pola te są zdefiniowane jako część opcji XSI w specyfikacji Single Unix.

W starszych wersjach standardu POSIX.1 pola związane z czasem były definiowane jako st_atime, st_mtimei st_ctime, oraz były typu time_t. Od wersji standardu z 2008 r. nazwy tych pól zostały zmienione odpowiednio na st_atim, st_mtimi st_ctim, typu struct timespec, ponieważ ta struktura zapewnia wyższą jednostkę czasu rozdzielczości. Ze względu na kompatybilność, implementacje mogą definiować stare nazwy pod względem tv_secczłonka struct timespec. Na przykład st_atimemożna zdefiniować jako st_atim.tv_sec.

W struct statskład struktury wchodzą co najmniej następujące elementy:

  • st_dev – identyfikator urządzenia zawierającego plik
  • st_ino – numer i- węzła
  • st_mode – tryb ochrony ; zobacz także uprawnienia Uniksa
  • st_nlink - Ilość referencyjna z twardych linków
  • st_uid – identyfikator użytkownika właściciela
  • st_gid – identyfikator grupy właściciela
  • st_rdev – identyfikator urządzenia (jeśli plik specjalny )
  • st_size – całkowity rozmiar pliku w bajtach
  • st_atime – czas ostatniego dostępu
  • st_mtime – czas ostatniej modyfikacji
  • st_ctime – czas ostatniej zmiany statusu
  • st_blksize – preferowany rozmiar bloku dla we/wy systemu plików, który może zależeć zarówno od systemu, jak i typu systemu plików
  • st_blocks – liczba bloków alokowanych w wielokrotnościach DEV_BSIZE(zwykle 512 bajtów).

st_modePole jest polem bitowym . Łączy w sobie tryby dostępu do plików, a także wskazuje każdy specjalny typ pliku . Istnieje wiele makr do pracy z różnymi flagami trybu i typami plików.

Krytyka czasu

Odczytywanie pliku zmienia jego czas, ostatecznie wymagając zapisu na dysku , co zostało skrytykowane, ponieważ jest niezgodne z systemem plików tylko do odczytu. Pamięć podręczna systemu plików może znacznie zmniejszyć tę aktywność do jednego zapisu na dysku na opróżnienie pamięci podręcznej.

Deweloper jądra Linuksa, Ingo Molnár, publicznie skrytykował koncepcję i wpływ atime na wydajność w 2007 roku, aw 2009 roku opcja montowania relatime stała się domyślną opcją, co rozwiązuje tę krytykę. Zachowanie opcji montowania relatime zapewnia wystarczającą wydajność dla większości celów i nie powinno zepsuć żadnych znaczących aplikacji, ponieważ zostało to szeroko omówione. Początkowo relatime aktualizowane tylko atime, jeśli atime < mtime lub atime < ctime; został on następnie zmodyfikowany, aby aktualizować czasy sprzed 24 godzin lub starsze, aby tmpwatch i licznik popularności Debiana (popcon) działały prawidłowo.

Aktualne wersje jądra Linux obsługują cztery opcje montowania, które można określić w fstab :

  • strictatime (dawniej atime , a dawniej domyślne; strictatime od 2.6.30) – zawsze aktualizuj atime, co jest zgodne z zachowaniem określonym przez POSIX
  • relatime („relative atime”, wprowadzone w 2.6.20 i domyślne od 2.6.30) – aktualizuj czas tylko w określonych okolicznościach: jeśli poprzedni czas jest starszy niż mtime lub ctime, lub poprzedni czas przekracza 24 godziny w przeszłość
  • nodiratime  – nigdy nie aktualizuj czasu katalogów, ale aktualizuj czas innych plików
  • noatime  – nigdy nie aktualizuj czasu żadnego pliku ani katalogu; implikuje nodiratime ; najwyższa wydajność, ale najmniej kompatybilny
  • lazytime  – aktualizuj czas zgodnie z określonymi poniżej okolicznościami

Obecne wersje Linux , macOS , Solaris , FreeBSD i NetBSD obsługują opcję montowania noatime w /etc/fstab , która powoduje, że pole atime nigdy nie jest aktualizowane. Wyłączenie aktualizacji w czasie łamie zgodność z POSIX , a niektóre aplikacje, takie jak powiadomienia o „nowej poczcie ” sterowane przez mbox oraz niektóre narzędzia do monitorowania użycia plików, w szczególności tmpwatch .

Opcja noatime w OpenBSD zachowuje się bardziej jak relatime Linuksa .

Wersja 4.0 głównej linii jądra Linuksa , która została wydana 12 kwietnia 2015 r., wprowadziła nową opcję montowania lazytime . Pozwala na dokonywanie aktualizacji atime w stylu POSIX w pamięci i opróżnianie ich na dysk wraz z niektórymi niezwiązanymi z czasem operacjami I/O na tym samym pliku; Aktualizacje atime są również opróżniane na dysk, gdy wykonywane są niektóre wywołania systemowe synchronizacji lub przed usunięciem i-węzła pliku z pamięci podręcznej systemu plików. Dodatkowo istnieje możliwość skonfigurowania czasu, przez jaki modyfikacje mogą pozostać nieopróżnione. W ten sposób lazytime zachowuje zgodność z POSIX, oferując jednocześnie ulepszenia wydajności.

ctime

Kuszące jest wiara, że cczas pierwotnie oznaczał czas stworzenia; jednak, podczas gdy wczesny Unix miał czasy modyfikacji i tworzenia, ten ostatni został zmieniony na czas dostępu, zanim pojawiła się jakakolwiek struktura C, w której można by wywołać cokolwiek ctime . Systemy plików zachowały tylko czas dostępu ( atime ) i czas modyfikacji ( mtime ) aż do szóstej edycji Uniksa. Ctime datownik dodano w restrukturyzacji systemu plików, który wystąpił z 7 edycji Unix, i zawsze, o których mowa czasu zmiany i-węzła. Jest on aktualizowany żadnych metadanych pliku czas przechowywane w zmianach iwęźle, takich jak uprawnienia do plików , własności plików oraz tworzenie i usuwanie twardych linków . W niektórych implementacjach zmiana nazwy pliku ma wpływ na ctime : Zarówno oryginalny Unix, który implementował zmianę nazwy poprzez utworzenie linku (aktualizacja ctime ), a następnie odłączenie starej nazwy ( ponowne zaktualizowanie ctime ), jak i nowoczesny Linux robią to.

W przeciwieństwie do atime i mtime , ctime nie można ustawić na dowolną wartość za pomocą funkcji utime() , jak to jest używane na przykład przez narzędzie touch . Zamiast tego, gdy używana jest utime() lub dla jakiejkolwiek innej zmiany w i-węźle innej niż aktualizacja atime spowodowana dostępem do pliku, wartość ctime jest ustawiana na bieżący czas.

Szczegółowość czasu

  • time_t podaje czasy z dokładnością do jednej sekundy.
  • Niektóre systemy plików zapewniają większą szczegółowość. Solaris 2.1 wprowadził rozdzielczość mikrosekundową z UFS w 1992 roku i rozdzielczość nanosekundową z ZFS.
  • W jądrach Linuksa 2.5.48 i nowszych struktura stat obsługuje rozdzielczość nanosekundową dla trzech pól znacznika czasu pliku. Są one widoczne jako dodatkowe pola w strukturze statystyk.
  • Rozdzielczość czasu tworzenia w systemie plików FAT wynosi 10 milisekund, podczas gdy rozdzielczość jego czasu zapisu to dwie sekundy, a czas dostępu ma rozdzielczość jednego dnia, więc pełni rolę daty dostępu.

Przykład

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

Bibliografia

Linki zewnętrzne