맨위로가기

Stat (시스템 호출)

"오늘의AI위키"는 AI 기술로 일관성 있고 체계적인 최신 지식을 제공하는 혁신 플랫폼입니다.
"오늘의AI위키"의 AI를 통해 더욱 풍부하고 폭넓은 지식 경험을 누리세요.

1. 개요

`stat`은 POSIX 운영 체제에서 파일의 상태 정보를 얻는 데 사용되는 시스템 호출 함수군이다. 이 함수들은 `sys/stat.h` 헤더 파일에 정의되어 있으며, `stat()`, `fstat()`, `lstat()` 함수를 포함한다. `stat()` 함수는 파일 이름을, `fstat()`은 파일 디스크립터를, `lstat()`은 파일 이름과 심볼릭 링크의 속성을 반환하는 데 사용된다. `stat` 구조체는 파일의 크기, 접근 권한, 소유자, 시간 정보 등 다양한 속성을 담고 있으며, 대용량 파일 지원을 위해 64비트 버전의 함수(stat64(), lstat64(), fstat64())도 제공된다. 파일 접근 시간(`atime`) 업데이트 정책은 성능 저하 논란이 있었으며, 리눅스 커널은 `relatime`, `noatime`, `lazytime` 등의 마운트 옵션을 통해 이를 개선했다.

더 읽어볼만한 페이지

  • 시스템 호출 - 포크 (시스템 호출)
    포크는 유닉스 계열 운영체제에서 새로운 프로세스를 생성하는 시스템 호출로, 호출 시 부모 프로세스의 복사본인 자식 프로세스가 생성되어 파일 서술자를 상속받으며, 유닉스 철학의 핵심 개념으로 필터 개발 및 파이프라인 구축에 용이하고 vfork, rfork, clone 등 다양한 변종이 존재한다.
  • 시스템 호출 - Chroot
    `chroot`는 유닉스 계열 운영체제에서 프로세스의 루트 디렉토리를 변경하는 시스템 호출 및 환경으로, 다양한 목적으로 사용되지만 보안 취약점과 제한 사항을 가지며, `fakechroot`는 root 권한 없이 유사한 환경을 제공한다.
  • C POSIX 라이브러리 - 포크 (시스템 호출)
    포크는 유닉스 계열 운영체제에서 새로운 프로세스를 생성하는 시스템 호출로, 호출 시 부모 프로세스의 복사본인 자식 프로세스가 생성되어 파일 서술자를 상속받으며, 유닉스 철학의 핵심 개념으로 필터 개발 및 파이프라인 구축에 용이하고 vfork, rfork, clone 등 다양한 변종이 존재한다.
  • C POSIX 라이브러리 - POSIX 스레드
    POSIX 스레드는 C 프로그래밍 언어에서 스레드를 생성, 관리, 동기화하는 데 사용되는 함수들의 모음으로, pthread.h 헤더 파일과 스레드 라이브러리로 구현된다.
  • POSIX - 오픈 그룹
    오픈 그룹은 다양한 기술 공급업체, 구매자, 정부 기관을 포함하는 국제 컨소시엄으로, 표준 개발, 인증 프로그램 운영, TOGAF와 같은 IT 아키텍처 프레임워크 제공 및 UNIX 상표 권리 보유를 통해 개방형 IT 표준 개발 및 보급에 기여한다.
  • POSIX - 본 셸
    본 셸은 스티븐 본이 개발하여 1979년 유닉스에 포함된 셸로, 셸 스크립트, 제어 흐름, 변수, 시그널 처리 등의 기능을 제공하며 여러 셸에 영향을 주었고 현재도 널리 사용된다.
Stat (시스템 호출)
일반 정보
시스템 호출 정보
정의 위치``
시스템유닉스 계열
반환 타입정수형 (int)
성공 시 반환 값0
실패 시 반환 값-1
함수 원형 (C)
함수 원형int stat(const char *path, struct stat *buf);
설명주어진 경로 이름(path)에 해당하는 파일의 상태 정보를 stat 구조체(buf)에 저장한다.
함수 원형int fstat(int fd, struct stat *buf);
설명열린 파일 디스크립터(fd)에 해당하는 파일의 상태 정보를 stat 구조체(buf)에 저장한다.
함수 원형int lstat(const char *path, struct stat *buf);
설명stat()과 유사하지만, 심볼릭 링크 자체의 정보를 반환한다. stat()은 심볼릭 링크가 가리키는 파일의 정보를 반환한다.
stat 구조체 멤버
st_dev파일이 위치한 장치 ID
st_inoi-노드 번호
st_mode파일 유형 및 모드 (권한)
st_nlink하드 링크 수
st_uid소유자 사용자 ID
st_gid소유자 그룹 ID
st_rdev장치 ID (특수 파일인 경우)
st_size파일 크기 (바이트)
st_atime마지막 접근 시간
st_mtime마지막 수정 시간
st_ctime마지막 상태 변경 시간
st_blksize파일 시스템 블록 크기
st_blocks할당된 블록 수
관련 명령어
관련 명령어ls 명령어는 파일 정보를 표시하는 데 사용되며, 내부적으로 stat() 시스템 호출을 사용한다.
예시ls -lu (마지막 접근 시간을 기준으로 정렬), ls -l (자세한 정보 표시), ls -lc (마지막 상태 변경 시간을 기준으로 정렬)

2. stat() 함수군

POSIX C 라이브러리의 `sys/stat.h` 헤더 파일은 `stat()`, `fstat()`, `lstat()` 함수를 정의한다. 이 함수들은 파일의 속성을 반환하는 `struct stat` 구조체에 대한 포인터를 인수로 받는다. 함수들은 성공하면 0을 반환하고, 오류가 발생하면 -1을 반환하며 errno가 적절하게 설정된다.[1]

`stat()`과 `lstat()` 함수는 파일 이름을 인수로 받는다. 심볼릭 링크인 경우, `stat()`은 링크가 가리키는 파일의 속성을, `lstat()`은 링크 자체의 속성을 반환한다. `fstat()` 함수는 파일 디스크립터를 인수로 받는다.[1]

대용량 파일 지원을 위해 `stat64()`, `lstat64()`, `fstat64()` 함수가 추가되었다. 이 함수들은 64비트 파일 크기를 지원하는 `struct stat64` 구조체를 사용하며, 2GiB 이상(최대 8EiB)의 파일에서 작동할 수 있다. `_FILE_OFFSET_BITS` C 매크로가 64로 정의된 경우, 64비트 함수를 원래 이름으로 사용할 수 있다.[1]

2. 1. stat() 함수

`stat()` 함수는 파일 이름을 인수로 받아 해당 파일의 정보를 `stat` 구조체에 저장한다. 심볼릭 링크의 경우, 링크가 가리키는 원본 파일의 정보를 반환한다.[1] 함수는 성공하면 0을 반환하고, 오류가 발생하면 -1을 반환하며 errno가 적절하게 설정된다.[1]

함수는 다음과 같이 정의된다.[1]

```c

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

2. 2. lstat() 함수

`lstat()` 함수는 `stat()` 함수와 유사하게 파일 이름을 인수로 받지만, 파일이 심볼릭 링크인 경우 링크의 대상 파일이 아닌 링크 자체의 속성을 반환한다. `stat()` 함수는 심볼릭 링크의 경우 링크가 가리키는 최종 대상의 속성을 반환한다는 점에서 차이가 있다.

함수 정의는 다음과 같다.

```c

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

```

POSIX C 라이브러리의 `sys/stat.h` 헤더에 선언되어 있으며, POSIX 및 기타 유닉스 계열 운영 체제에서 사용 가능하다. 함수는 성공하면 0, 오류가 발생하면 -1을 반환하며, 오류 시 errno가 설정된다.

대용량 파일 지원을 위해 확장된 `lstat64()` 함수도 제공된다. 이 함수는 64비트 파일 크기를 지원하는 `struct stat64` 구조체를 사용하여 2GiB 이상의 파일(최대 8EiB)에서도 작동할 수 있다. `_FILE_OFFSET_BITS` C 매크로가 64로 정의되면 `lstat64()` 함수를 `lstat()` 이름으로 사용할 수 있다.

2. 3. fstat() 함수

`fstat()` 함수는 파일 디스크립터를 인수로 받아 해당 파일의 정보를 `stat` 구조체에 저장한다. 함수는 성공하면 0을 반환하고, 오류가 발생하면 -1을 반환하며 errno가 적절하게 설정된다.

함수 정의는 다음과 같다:



int fstat(int filedesc, struct stat *buf);



POSIX C 라이브러리의 헤더 `sys/stat.h`는 `fstat()` 함수를 선언한다. 이 함수는 파일 속성을 반환하는 데 사용되는 `struct stat` 버퍼 인자에 대한 포인터를 인수로 받는다.

대용량 파일 지원을 위해 확장된 `fstat64()` 함수는 64비트 유형으로 파일 크기를 나타내는 `struct stat64` 구조체에 속성을 반환한다. 이를 통해 2GiB 이상(최대 8EiB)의 파일에서 작동할 수 있다. `_FILE_OFFSET_BITS` C 매크로가 64로 정의된 경우, `fstat64()` 함수는 `fstat()` 이름으로 사용할 수 있다.

2. 4. 대용량 파일 지원

64비트 시스템에서는 `stat64()`, `lstat64()`, `fstat64()` 함수를 사용하여 2GiB 이상의 대용량 파일 정보를 처리할 수 있다. 이 함수들은 파일 크기를 64비트 유형으로 나타내는 `struct stat64` 구조에 속성을 반환하며, 최대 8EiB 크기의 파일까지 지원한다. `_FILE_OFFSET_BITS` C 매크로가 64로 정의된 경우, 원래 이름(stat, lstat, fstat)으로 64비트 함수를 사용할 수 있다.

3. stat 구조체

`stat` 구조체는 파일 정보를 담는 자료 구조이며, `sys/stat.h` 헤더 파일에 정의되어 있다.[2] 구현에 따라 추가 필드를 정의할 수도 있다.

POSIX.1은 `st_rdev`, `st_blocks`, `st_blksize` 멤버를 요구하지 않지만, 이들은 Single Unix Specification의 XSI 옵션에 정의되어 있다.

2008년 이전 POSIX.1 표준에서는 시간 관련 필드를 `st_atime`, `st_mtime`, `st_ctime` (time_t|타임_t영어 형식)으로 정의했다. 2008년 이후 표준에서는 `st_atim`, `st_mtim`, `st_ctim`으로 변경하고, 더 높은 해상도의 시간 단위를 제공하는 `timespec` 구조체 형식을 사용한다. 호환성을 위해 이전 이름은 `struct timespec`의 `tv_sec` 멤버를 사용하여 정의할 수 있다. (예: `st_atime`은 `st_atim.tv_sec`).[2]

`stat` 구조체는 다음과 같이 정의된다.

```c

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;

};

```

`st_mode` 필드는 비트 필드로, 파일 접근 모드와 특수 파일 유형을 나타낸다.

3. 1. 주요 멤버

`stat` 구조체는 파일의 정보를 담고 있으며, `sys/stat.h` 헤더 파일에 정의되어 있다. 구현에 따라 추가 필드가 정의될 수도 있다.[2] POSIX.1은 `st_rdev`, `st_blocks`, `st_blksize` 멤버를 요구하지 않지만, 이 필드들은 Single Unix Specification의 XSI 옵션의 일부로 정의되어 있다.

2008년 이전 POSIX.1 표준에서는 시간 관련 필드가 `st_atime`, `st_mtime`, `st_ctime`으로 정의되었고, `time_t` 형식을 사용했다. 하지만 2008년 표준 이후, 더 높은 해상도의 시간 단위를 제공하기 위해 `timespec` 구조체를 사용하며, 필드 이름도 `st_atim`, `st_mtim`, `st_ctim`으로 변경되었다. 호환성을 위해 이전 이름(예: `st_atime`)은 `st_atim.tv_sec`과 같이 정의될 수 있다.[2]

`struct stat` 구조체의 주요 멤버는 다음과 같다.

멤버설명비고
`st_dev`파일을 포함하는 장치의 식별자
`st_ino`아이노드 번호
`st_mode`파일 종류 및 접근 권한파일 모드를 나타내는 비트 필드
`st_nlink`하드 링크
`st_uid`파일 소유자의 사용자 식별자
`st_gid`파일 소유 그룹의 그룹 식별자
`st_rdev`장치 파일의 경우 장치 식별자
`st_size`파일 크기 (바이트 단위)
`st_atime`
`st_mtime`
`st_ctime`
`st_blksize`파일 시스템 I/O 블록 크기시스템 및 파일 시스템 유형에 따라 달라질 수 있음[2]
`st_blocks`파일에 할당된 블록 수일반적으로 512바이트의 배수


3. 2. 시간 정보 (st_atime, st_mtime, st_ctime)

POSIX.1 표준의 이전 버전에서는 시간 관련 필드를 `st_atime`, `st_mtime`, `st_ctime`으로 정의하고, time_t|타임_t영어 형식을 사용했다. 2008년 표준 이후, 이 필드들은 `st_atim`, `st_mtim`, `st_ctim`으로 이름이 변경되었고, `timespec` 구조체 형식을 사용하도록 변경되었다. `timespec` 구조체는 더 높은 해상도의 시간 단위를 제공하기 때문이다. 호환성을 위해 구현에서는 `struct timespec`의 `tv_sec` 멤버를 사용하여 이전 이름을 정의할 수 있다. 예를 들어 `st_atime`은 `st_atim.tv_sec`으로 정의할 수 있다.[2]

  • `st_atime`: 파일에 마지막으로 접근한 시간을 나타낸다. 파일을 읽거나 실행하는 등의 작업이 발생하면 이 시간이 업데이트된다.
  • `st_mtime`: 파일의 내용이 마지막으로 수정된 시간을 나타낸다. 파일의 내용이 변경되면 이 시간이 업데이트된다.
  • `st_ctime`: 파일의 상태 정보(소유권, 권한, 링크 수 등)가 마지막으로 변경된 시간을 나타낸다. 파일 내용이 수정될 때도 `st_ctime`은 함께 업데이트된다.


`st_atime` 및 `st_mtime`과 달리 `st_ctime`은 touch영어 유틸리티에서 사용되는 `utime()` 함수를 사용하여 임의의 값으로 설정할 수 없다. 대신, `utime()` 함수가 사용되거나 파일 접근으로 인해 `st_atime`이 업데이트되는 경우, 또는 inode에 대한 다른 변경 사항이 발생하면 `st_ctime` 값은 현재 시간으로 설정된다.[13]

4. atime 업데이트 정책 (Criticism of atime)

파일을 읽기만 해도 해당 파일의 `atime`이 변경되어 디스크 쓰기 작업이 필요하게 되는 것은, 읽기 전용 파일 시스템과 맞지 않아 비판받아왔다. 파일 시스템 캐시는 이러한 작업을 캐시 플러시당 한 번의 디스크 쓰기로 줄일 수 있지만, 여전히 성능 저하의 원인이 될 수 있다.

리눅스 커널 개발자인 잉고 몰나르는 2007년에 atime의 개념과 성능 저하를 공개적으로 비판했으며,[3][4] 2009년에는 `relatime` 마운트 옵션이 기본값으로 설정되어 이러한 문제를 해결했다.[5] `relatime`은 대부분의 목적에 충분한 성능을 제공하며, 널리 논의되어 중요한 응용 프로그램을 손상시키지 않는다.[6]

리눅스는 `atime` 업데이트 정책을 개선하기 위해 다양한 마운트 옵션을 제공한다. (자세한 내용은 하위 섹션 '리눅스 마운트 옵션' 참고)

현재 리눅스, macOS, 솔라리스, FreeBSD, NetBSD 버전은 /etc/fstab에서 `noatime` 마운트 옵션을 지원하며, 이 옵션은 atime 필드가 업데이트되지 않도록 한다. atime 업데이트를 끄면 POSIX를 준수하지 않게 되며, "새로운 메일" 알림을 위한 mbox 기반 애플리케이션[8] 및 tmpwatch와 같은 일부 파일 사용 감시 유틸리티가 손상될 수 있다.

OpenBSD의 `noatime` 옵션은 리눅스 `relatime`과 유사하게 동작한다.[9]

4. 1. 리눅스 마운트 옵션

리눅스 커널은 fstab에서 지정할 수 있는 다음과 같은 마운트 옵션을 지원한다.

옵션설명
`strictatime`항상 atime을 업데이트하여 POSIX 표준을 따른다. (과거에는 `atime`으로 불렸으며, 2.6.30 이전에는 기본값이었음)
`relatime`특정 상황에서만 atime을 업데이트한다. 이전 atime이 mtime 또는 ctime보다 오래되었거나, 24시간 이상 지난 경우에 업데이트한다. (2.6.20에 도입, 2.6.30부터 기본값)[5][7]
`nodiratime`디렉터리의 atime은 업데이트하지 않지만, 다른 파일의 atime은 업데이트한다.
`noatime`파일이나 디렉터리의 atime을 업데이트하지 않는다. (`nodiratime`을 포함한다) 최고의 성능을 제공하지만, POSIX 호환성이 가장 낮다.
`lazytime`메모리 상에서 atime 업데이트를 수행하고, 특정 상황에 따라 디스크에 반영한다. POSIX 호환성을 유지하면서 성능을 향상시킨다.[10][11]



`lazytime` 옵션은 2015년 4월 12일에 출시된 리눅스 커널 메인라인 버전 4.0에서 도입되었다.[10][11] 이 옵션을 사용하면 POSIX 스타일의 atime 업데이트를 메모리 내에서 수행하고, 다음 조건에 해당될 때 디스크에 반영한다.


  • 동일한 파일에 대한 일부 시간 관련 I/O 작업
  • sync 시스템 호출 실행
  • 파일의 메모리 내 아이노드가 파일 시스템 캐시에서 제거되기 전


또한 atime 수정이 디스크에 반영되지 않은 상태로 유지될 수 있는 기간을 구성할 수 있다.

5. 시간 정밀도 (Time granularity)

time_t영어는 1초 단위의 시간 정보를 제공한다.

일부 파일 시스템은 더 세밀한 정밀도를 제공한다. 솔라리스 2.1은 1992년에 UFS에서 마이크로초 해상도를, ZFS에서 나노초 해상도를 도입했다.

리눅스 커널 2.5.48 이상에서는 stat 구조체가 세 가지 파일 타임스탬프 필드에 대해 나노초 해상도를 지원한다. 이들은 stat 구조체의 추가 필드로 노출된다.[14][15]

FAT 파일 시스템의 생성 시간 해상도는 10밀리초이고, 쓰기 시간 해상도는 2초이며, 접근 시간 해상도는 하루이므로 접근 날짜 역할을 한다.[16]

6. 예제

c

#include

#include

#include

#include

#include

#include

#include

int

main(int argc, char *argv[])

{

struct stat sb;

struct passwd *pwuser;

struct group *grpnam;

if (argc < 2)

{

fprintf(stderr, "사용법: %s: 파일 ...\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("\n");

}

return 0;

}

```

다음은 C 언어를 사용한 `stat()` 함수 사용 예제이다.

참조

[1] 간행물 A Research Unix reader: annotated excerpts from the Programmer's Manual, 1971–1986 http://www.cs.dartmo[...]
[2] 웹사이트 "" http://pubs.opengrou[...] The Open Group
[3] 뉴스 Linux: Replacing atime With relatime http://kerneltrap.or[...] Kernel Trap 2007-08-07
[4] 뉴스 Once upon atime https://lwn.net/Arti[...] LWN 2007-08-08
[5] 웹사이트 Linux kernel 2.6.30 http://kernelnewbies[...] Linux Kernel Newbies
[6] 뉴스 That massive filesystem thread https://lwn.net/Arti[...] LWN 2009-03-31
[7] 웹사이트 Relatime Recap https://archive.toda[...]
[8] 문서 "the shell's $MAIL monitor ... depends on atime, pronouncing new email with atime($MAIL) < mtime($MAIL)" http://www.mail-arch[...]
[9] 웹사이트 mount(2) - OpenBSD manual pages https://man.openbsd.[...] 2018-04-27
[10] 웹사이트 Linux kernel 4.0, Section 1.5. 'lazytime' option for better update of file timestamps http://kernelnewbies[...] 2015-05-01
[11] 웹사이트 Introducing lazytime https://lwn.net/Arti[...] LWN.net 2014-11-19
[12] 웹사이트 BSTJ version of C.ACM Unix paper https://www.bell-lab[...]
[13] 웹사이트 pwrite, write - write on a file https://pubs.opengro[...]
[14] 웹사이트 stat(2) - Linux manual page http://man7.org/linu[...] man7.org 2015-02-27
[15] 간행물 struct stat.h with nanosecond resolution http://www.sourcewar[...] mail archive of the libc-alpha@sources.redhat.com mailing list for the glibc project. 2002-12-02
[16] 웹사이트 MSDN: File Times http://msdn.microsof[...]



본 사이트는 AI가 위키백과와 뉴스 기사,정부 간행물,학술 논문등을 바탕으로 정보를 가공하여 제공하는 백과사전형 서비스입니다.
모든 문서는 AI에 의해 자동 생성되며, CC BY-SA 4.0 라이선스에 따라 이용할 수 있습니다.
하지만, 위키백과나 뉴스 기사 자체에 오류, 부정확한 정보, 또는 가짜 뉴스가 포함될 수 있으며, AI는 이러한 내용을 완벽하게 걸러내지 못할 수 있습니다.
따라서 제공되는 정보에 일부 오류나 편향이 있을 수 있으므로, 중요한 정보는 반드시 다른 출처를 통해 교차 검증하시기 바랍니다.

문의하기 : help@durumis.com