Stat (시스템 호출)
"오늘의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_ino | i-노드 번호 |
| 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]
웹사이트
"
[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