file 파일
보조기억장치에 저장된 관련 정보의 이름 있는 집합체. 프로세스가 종료되어도 유지되며(persistent), OS는 file을 통해 정보 저장의 균일한 논리적 뷰를 제공한다.
파일 시스템의 기본 개념부터 디렉토리 구조, 마운팅, 온디스크/인메모리 자료구조, VFS까지 슬라이드 순서대로 정리한다.
file system은 보조기억장치 위에서 file을 추상화하고 논리적으로 조직화하는 계층이다. 파일은 이름, 속성(attributes/메타데이터), 데이터로 구성되며, file system은 이를 디스크 블록 집합에 매핑하는 문제를 해결한다. directory는 파일에 대한 구조화된 명명 인터페이스를 제공하고, pathname translation을 통해 논리적 파일 경로가 실제 블록 위치로 변환된다.
디스크 레이아웃은 boot block, super block, bitmaps(여유 공간 관리), i-nodes(파일 메타데이터), 루트 디렉토리, 파일·디렉토리 데이터 영역으로 구성된다. 메모리에는 in-memory partition table, 시스템 전역 open-file table, 프로세스별 file descriptor table, directory cache, buffer cache가 유지된다. VFS(Virtual File System)는 커널 수준에서 모든 구체적인 파일 시스템(ext4, NFS, FAT 등)을 단일 인터페이스로 추상화한다.
file system mounting은 파일 시스템을 프로세스가 사용할 수 있도록 특정 디렉토리(mount point)에 붙이는 과정이다. Linux VFS는 superblock object, dentry object, inode object, file object 네 가지 핵심 객체로 구성된다.
보조기억장치에 저장된 관련 정보의 이름 있는 집합체. 프로세스가 종료되어도 유지되며(persistent), OS는 file을 통해 정보 저장의 균일한 논리적 뷰를 제공한다.
보조기억장치에 대한 추상화(file)를 구현하고, 파일을 논리적으로 조직화(directory)하며, 데이터 공유와 접근 보호를 제공하는 OS 구성요소. 핵심 문제는 <파일명, 메타데이터, 데이터>를 디스크 블록 집합에 매핑하는 것이다.
파일 이름 외에 파일을 설명하는 부가 정보. 파일 크기, 소유자, 접근 제어 목록(ACL), 생성·최종 접근·최종 수정 시각, 보호 비트 등을 포함한다. 파일 시스템은 보통 파일 내용의 의미에는 관여하지 않는다.
파일에 적용할 수 있는 시스템 콜의 집합. UNIX 기준 주요 연산: creat(), open(), close(), read(), write(), lseek(), stat(), chmod(), chown(), flock(), fcntl().
커널이 관리하는 두 단계 자료구조. 시스템 전역 open-file table은 열린 파일마다 속성과 참조 카운트를 저장하고, 프로세스별 file descriptor table은 fd를 전역 테이블 항목에 연결하며 현재 오프셋을 보관한다.
open() 호출이 성공하면 반환되는 정수 인덱스. 프로세스별 file descriptor table의 항목을 가리키며, 이후 read()/write()/close() 호출에 사용된다.
사용자에게는 파일을 구조화하는 인터페이스를, 파일 시스템에는 편리한 명명 인터페이스를 제공한다. current directory(작업 디렉토리) 개념을 지원하며, relative path와 absolute path를 통해 파일에 접근한다.
디렉토리는 보통 특수 메타데이터를 담는 파일로 구현된다. 내용은 (파일명, 파일 속성) 쌍의 목록이며, 일반적으로 정렬되지 않은 상태로 저장된다. 크기, 보호, 생성 시각, 접근 시각, 디스크 위치 등의 속성을 포함한다.
open("/a/b/c", …)처럼 경로를 파일의 실제 위치로 변환하는 과정. 루트 디렉토리("/"는 항상 찾을 수 있음)에서 시작하여 경로 구성요소마다 디렉토리를 탐색하고 권한을 검사한다. 비용이 크기 때문에 open()이 read()/write()와 분리된 이유이다.
absolute path는 루트("/")에서 시작하는 전체 경로(예: /tmp/foo/bar).
relative path는 현재 작업 디렉토리를 기준으로 한 경로(예: ../foo/bar).
대부분의 파일 시스템은 두 형식을 모두 지원한다.
파일 시스템을 프로세스에게 접근 가능하게 만들기 위해 특정 디렉토리에 붙이는 작업.
Windows는 드라이브 문자(예: C:\)를 사용하고,
Unix/Linux는 기존 빈 디렉토리(mount point)에 마운트한다.
Unix에서 파일 시스템이 마운트되는 기존 빈 디렉토리. 마운트 후 해당 디렉토리에 접근하면 새로 붙인 파일 시스템의 루트로 진입한다.
파티션의 온디스크 구성: boot block(부팅 코드), super block(파일 시스템 메타데이터), bitmaps(여유 공간 관리 자료구조), i-nodes(파일 메타데이터), 루트 디렉토리, 파일·디렉토리 데이터 블록.
boot block은 OS를 부팅하는 코드와 정보를 담는 파티션의 첫 블록이다. super block은 파일 시스템 유형, 총 블록 수 등 볼륨 전체 메타데이터를 저장하는 파일 시스템 필수 구조체이다.
파일 시스템 성능을 위해 메모리에 유지되는 구조체들. in-memory partition table, 시스템 전역 open-file table, 프로세스별 file descriptor table, directory cache, buffer cache가 포함된다.
커널 수준에서 모든 파일 시스템을 단일 포맷으로 관리하는 추상화 계층. 사용자 레벨의 시스템 콜(open, read, write, close 등)을 받아 mount point 탐색을 통해 특정 파일 시스템과 상호작용한다. Linux VFS의 네 핵심 객체: superblock object, dentry object, inode object, file object.
파일 하나당 존재하는 온디스크 메타데이터 구조체. 파일 크기, 소유자, 권한, 타임스탬프, 데이터 블록 포인터 등을 저장한다. UNIX 계열에서는 inode라고 부른다. 파일 이름은 inode에 없고 디렉토리 엔트리에만 존재한다.
장기 정보 저장에는 세 가지 요구사항이 있다: (1) 대량의 정보를 저장할 수 있어야 하고, (2) 프로세스가 종료되어도 정보가 유지되어야 하며, (3) 여러 프로세스가 동시에 정보에 접근할 수 있어야 한다. 이를 충족하는 추상화가 file이다.
file은 보조기억장치에 기록된 관련 정보의 이름 있는 집합체로, 전원 장애나 시스템 재부팅에서도 살아남는다. file system은 이 파일을 추상화·조직화하고 공유와 보호를 제공한다.
블록 디바이스 드라이버가 제공하는 추상화는 고정 크기(512 B) 섹터의 선형 배열이다.
지원 연산은 Identify()(총 섹터 수 반환), Read(시작 섹터, 개수),
Write(시작 섹터, 개수) 세 가지뿐이다.
file system은 이 단순한 인터페이스 위에서 파일·디렉토리 추상화를 구축한다.
파일 하나는 세 가지 요소로 구성된다: 파일 이름, file attributes(메타데이터), 파일 내용(데이터).
파일 시스템은 보통 파일 내용의 의미에는 관여하지 않는다.
파일 접근은 반드시 파일 이름에서 시작한다(예: open("/etc/passwd", O_RDONLY)).
file attributes에는 다음과 같은 정보가 포함된다:
UNIX 파일 연산(file operations) 시스템 콜:
| 시스템 콜 | 설명 |
|---|---|
creat(pathname, mode) |
새 파일 생성 |
open(pathname, flags, mode) |
파일 열기, 파일 디스크립터 반환 |
close(fd) |
파일 닫기 |
read(fd, buf, count) |
파일에서 데이터 읽기 |
write(fd, buf, count) |
파일에 데이터 쓰기 |
lseek(fd, offset, whence) |
파일 오프셋 이동 |
stat(pathname, buf) |
파일 속성(메타데이터) 조회 |
chmod(pathname, mode) |
파일 권한 변경 |
chown(pathname, owner, grp) |
파일 소유자/그룹 변경 |
flock(fd, operation) |
파일 잠금(lock) 설정 |
fcntl(fd, cmd, arg) |
파일 제어 명령 |
directory는 두 가지 역할을 한다. 사용자에게는 파일을 구조화된 방식으로 조직하는 수단을 제공하고, 파일 시스템에게는 논리적 파일 조직과 물리적 디스크 배치를 분리하는 편리한 명명 인터페이스를 제공한다.
대부분의 파일 시스템은 계층적 디렉토리 구조를 지원한다:
cd ../../../foo/bar/../bar)cd /tmp/foo/bar)디렉토리 내부(Directory Internals): 디렉토리는 일반적으로 특수 메타데이터를 담는 파일이다. 내용은 (파일명, 파일 속성) 쌍의 목록으로, 보통 정렬되지 않은 순서로 저장된다 (정렬은 디렉토리를 읽는 프로그램이 수행). 속성에는 크기, 보호, 생성 시각, 접근 시각, 디스크 상의 위치 등이 포함된다.
pathname translation은 open("/a/b/c", …)와 같은 경로를 파일의 실제 위치로 변환하는 과정이다.
단계별 처리:
시스템은 디렉토리 경로를 내려가는 데 많은 시간을 소비한다.
이 때문에 open()이 read()/write()와 분리되어 있다.
(read("/a/b/c", buf, 100)처럼 매 읽기마다 경로 탐색을 반복하면 비효율적이다.)
OS는 접두사 탐색 결과를 캐시하여 성능을 향상시킨다.
예를 들어 /a/b, /a/bb, /a/bbb는 모두 "/a" 접두사를 공유하므로
"/a"까지의 탐색 결과를 재활용할 수 있다.
UNIX에서 디렉토리는 파일로 구현되므로, 기본적으로 파일 연산을 통해 조작할 수 있다. C 런타임 라이브러리는 디렉토리 읽기를 위한 고수준 추상화를 제공한다:
DIR *opendir(const char *name): 디렉토리 열기struct dirent *readdir(DIR *dir): 다음 디렉토리 항목 읽기void seekdir(DIR *dir, off_t offset): 디렉토리 오프셋 이동int closedir(DIR *dir): 디렉토리 닫기기타 디렉토리 관련 시스템 콜:
int rename(const char *oldpath, const char *newpath): 파일/디렉토리 이름 변경int link(const char *oldpath, const char *newpath): 하드 링크 생성int unlink(const char *pathname): 파일 링크 제거(파일 삭제)파일 시스템은 사용되기 전에 반드시 mounted 상태여야 한다. 마운트 방식은 운영체제에 따라 다르다:
| 운영체제 | 마운트 대상 | 예시 |
|---|---|---|
| Windows | 드라이브 문자(drive letters) | C:\, D:\, … |
| Unix/Linux | 기존 빈 디렉토리(mount point) | /mnt/usb, /home, … |
Unix에서는 디렉토리 트리의 임의 위치에 여러 파일 시스템을 마운트할 수 있어, 사용자는 단일 통합된 네임스페이스로 모든 파일 시스템에 접근한다.
온디스크(On-disk) 레이아웃: 파티션은 파일 시스템에 종속적(FS-dependent)인 영역으로 나뉜다.
| 영역 | 역할 |
|---|---|
| boot block | OS 부팅 코드 (파티션에 OS가 없으면 비어 있음); MBR(Master Boot Record)은 디스크 맨 앞에 위치 |
| super block | 파일 시스템 메타데이터: 유형, 총 블록 수 등 파일 시스템 전체 정보 |
| bitmaps | 여유 공간 관리를 위한 자료구조 |
| i-nodes | 파일 메타데이터 (파일마다 하나씩 존재); 루트 디렉토리 포함 |
| 파일 & 디렉토리 데이터 | 실제 파일 내용과 디렉토리 항목 데이터 블록 |
인메모리(In-memory) 자료구조: 파일 시스템 성능을 높이기 위해 메모리에 유지되는 구조체들이다.
| 자료구조 | 범위 | 내용 |
|---|---|---|
| in-memory partition table | 시스템 전역 | 마운트된 파티션 정보 |
| 시스템 전역 open-file table | 시스템 전역 | 열린 파일마다 참조 카운트(count), 오프셋, 파일 속성 보관 |
| 프로세스별 file descriptor table | 프로세스별 | fd를 전역 open-file table 항목에 매핑 |
| directory cache | 시스템 전역 | 최근 탐색한 디렉토리 항목 캐시 — pathname 탐색 가속 |
| buffer cache | 시스템 전역 | 최근 읽은 디스크 블록 캐시 — 반복 I/O 최적화 |
File System Internals — 계층 구조: 시스템 콜 인터페이스 → VFS → 각 구체 파일 시스템 드라이버(minix, nfs, ext4, fat, mmfs, procfs 등) → buffer cache → device driver 순으로 구성된다.
VFS(Virtual File System)는 커널 수준에서 모든 파일 시스템 구현을 단일 포맷으로 관리하는 추상화 계층이다.
Linux VFS 공통 파일 모델 — 네 가지 핵심 객체:
| 객체 | 저장 정보 |
|---|---|
| superblock object | 마운트된 파일 시스템에 관한 정보 (총 블록 수, 블록 크기, 루트 inode 등) |
| dentry object | 디렉토리 항목과 대응하는 파일 간의 링크 정보; dentry cache에 캐시되어 pathname 탐색 가속 |
| inode object | 특정 파일의 일반 정보 (크기, 권한, 타임스탬프, 데이터 블록 포인터) |
| file object | 열린 파일과 프로세스 간의 상호작용 정보 (현재 오프셋, 접근 모드) |
각 구체 파일 시스템은 이 네 객체에 대한 함수 포인터 테이블(operations table)을 구현한다. VFS는 이 포인터를 통해 특정 파일 시스템과 통신하므로, 사용자 프로세스는 ext4 파일과 NFS 파일을 동일한 read() 시스템 콜로 접근할 수 있다.
Q1
pathname translation 과정을 open("/a/b/c", O_RDONLY)를 예로 들어
단계별로 서술하고, open()이 read()/write()와
분리되어 있는 이유를 설명하시오.
pathname translation 단계:
open()과 read()/write() 분리 이유:
시스템이 디렉토리 경로를 내려가는 데 상당한 시간을 소비하기 때문이다.
read("/a/b/c", buf, 100)처럼 매번 경로 탐색을 포함하면
동일 파일을 반복 읽을 때마다 불필요한 pathname translation 비용이 발생한다.
open()으로 한 번 파일 디스크립터를 얻고 나면,
이후 read()/write()는 경로 재탐색 없이 직접 파일에 접근한다.
또한 OS는 접두사 탐색 결과를 캐시(prefix cache)하여 성능을 추가로 향상시킨다.
Q2 파일을 open()할 때 운영체제 내부에서 일어나는 자료구조 흐름을 directory, inode, 시스템 전역 open-file table, 프로세스별 file descriptor table 관점에서 단계별로 서술하시오.
Q3 file system mounting의 개념을 설명하고, Unix와 Windows의 마운팅 방식을 비교하시오. 또한 Unix에서 mount point의 역할을 서술하시오.
파일 시스템 마운팅: 파일 시스템은 프로세스가 사용하기 전에 반드시 마운트되어야 한다. 마운팅은 특정 파일 시스템을 시스템의 디렉토리 트리(또는 네임스페이스)에 연결하는 작업이다.
Windows 방식: 파일 시스템을 드라이브 문자(drive letter)에 연결한다(예: C:\, D:\). 각 드라이브는 독립적인 네임스페이스를 가지며, 드라이브 간 이동 시 문자를 명시해야 한다.
Unix/Linux 방식: 기존 빈 디렉토리(mount point)에 파일 시스템을 마운트한다. 마운트 후 해당 디렉토리에 접근하면 새로 붙인 파일 시스템의 루트로 진입한다. 전체 시스템이 단일 통합 디렉토리 트리를 형성하여 파일 시스템 종류와 위치를 투명하게 추상화한다.
mount point의 역할: VFS는 pathname 탐색 중 mount point를 만나면 해당 디렉토리 아래의 요청을 마운트된 파일 시스템으로 라우팅한다. 이를 통해 ext4, NFS, FAT 등 이질적인 파일 시스템이 단일 트리에 공존할 수 있다.
Q4 VFS(Virtual File System)의 역할과 이점을 설명하고, Linux VFS의 네 가지 핵심 객체(superblock object, dentry object, inode object, file object)가 각각 어떤 정보를 저장하는지 서술하시오.
VFS의 역할: 커널 수준에서 모든 파일 시스템 구현을 단일 포맷으로 관리하는 추상화 계층이다. 사용자 레벨 시스템 콜(open, read, write, close, stat 등)을 수신하여 mount point 탐색을 통해 적절한 구체 파일 시스템으로 요청을 라우팅한다.
VFS의 이점: 응용 프로그램이 파일 시스템 종류를 알 필요 없이 동일한 시스템 콜 인터페이스로 접근 가능하다. ext4 파일과 NFS 파일을 동일한 read()로 접근하며, 이질적인 파일 시스템을 단일 디렉토리 트리에 공존시킬 수 있다. 커널 모듈화와 응용 이식성을 동시에 달성한다.
Linux VFS 네 가지 핵심 객체:
Q5 파일 시스템의 온디스크(on-disk) 구조와 인메모리(in-memory) 구조를 구분하여 설명하고, 각 구조의 역할을 서술하시오.
온디스크 구조 (Disk Layout): 파티션은 다음 영역으로 구성된다.
인메모리 구조 (In-memory Structures): 파일 시스템 성능을 높이기 위해 메모리에 유지된다.
온디스크 구조는 영속성을 담당하고, 인메모리 구조는 성능 향상을 담당한다.
Q6 directory의 역할과 내부 구조를 설명하고, 계층적 디렉토리 시스템에서 absolute path와 relative path의 차이를 예를 들어 설명하시오.
directory의 역할: 사용자에게는 파일을 구조화된 방식으로 조직하는 수단을 제공하고, 파일 시스템에게는 논리적 파일 조직과 물리적 디스크 배치를 분리하는 편리한 명명 인터페이스를 제공한다.
directory 내부 구조: 디렉토리는 특수 메타데이터를 담는 파일로 구현된다. 내용은 (파일명, 파일 속성) 쌍의 목록이며 보통 정렬되지 않은 순서로 저장된다 (정렬은 디렉토리를 읽는 프로그램이 수행). 각 항목의 속성에는 크기, 보호, 생성 시각, 접근 시각, 디스크 상의 위치(inode 번호 등)가 포함된다.
absolute path vs. relative path:
cd /tmp/foo/bar
cd ../../../foo/bar/../bar
(..은 상위 디렉토리를 의미)
Q7 file system이 해결해야 하는 핵심 설계 문제들을 나열하고, 스토리지의 논리적 뷰(Storage: A Logical View)에서 블록 디바이스 드라이버가 제공하는 추상화와 그 한계를 설명하시오.
블록 디바이스 드라이버의 추상화: 블록 디바이스 드라이버는 디스크를 고정 크기(512 B) 섹터의 선형 배열로 추상화한다. 지원 연산은 세 가지뿐이다:
Identify(): 총 섹터 수 N을 반환Read(시작 섹터 번호, 섹터 개수): 지정 범위 읽기Write(시작 섹터 번호, 섹터 개수): 지정 범위 쓰기이 인터페이스는 매우 단순하여 파일 이름, 메타데이터, 디렉토리 구조 등 상위 개념을 전혀 지원하지 않는다. file system은 이 단순한 블록 인터페이스 위에서 파일·디렉토리 추상화를 구축해야 한다.
파일 시스템의 핵심 설계 문제:
목표는 성능(Performance)과 신뢰성(Reliability)의 균형이다.