Skip to content

Split View: [운영체제] 15. 파일 시스템 내부 구조

|

[운영체제] 15. 파일 시스템 내부 구조

파일 시스템 내부 구조

파일 시스템 구현의 기본 원리를 살펴본 후, 이제 실제 파일 시스템의 내부 구조와 성능 최적화 기법을 더 깊이 알아봅니다. ext4, APFS 등 현대 파일 시스템의 구조와 NFS를 포함한 네트워크 파일 시스템도 다룹니다.


1. 파일 시스템 마운팅

운영체제는 파일 시스템을 사용하기 전에 마운트해야 합니다. 마운트는 파일 시스템을 디렉토리 트리의 특정 지점(마운트 포인트)에 연결하는 것입니다.

마운트 전:                    마운트 후:
     / (루트)                      / (루트)
    ╱    ╲                       ╱    ╲
  home   mnt                   home   mnt
 (비어 있음)          │      │
 user1                        user1  ┌──────────────┐
USB 드라이브 │
                                      (ext4)                                     │  photos/                                     │  docs/                                     └──────────────┘
                              /mnt/photos 로 접근 가능
# 마운트 명령어 예시
# 장치를 마운트 포인트에 연결
mount /dev/sdb1 /mnt

# 특정 파일 시스템 타입 지정
mount -t ext4 /dev/sdb1 /mnt

# 읽기 전용 마운트
mount -o ro /dev/sdb1 /mnt

# 현재 마운트 목록 확인
mount | column -t

# 언마운트
umount /mnt

/etc/fstab 파일

부팅 시 자동으로 마운트할 파일 시스템을 정의합니다.

# /etc/fstab 예시
# 장치            마운트포인트  타입   옵션            덤프 패스
/dev/sda1         /            ext4   defaults         0    1
/dev/sda2         /home        ext4   defaults         0    2
/dev/sdb1         /data        xfs    noatime          0    2
tmpfs             /tmp         tmpfs  size=2G          0    0

2. 파티션과 블록 그룹

디스크 파티션 구조

┌──────────────────────────────────────────────────┐
│                물리 디스크                         │
│                                                  │
│  ┌─────┬────────────┬────────────┬────────────┐  │
│  │ MBRPartition 1Partition 2Partition 3│  │
│  │      (ext4)      (swap)      (ext4)     │  │
│  │     │ /          │            │ /home      │  │
│  └─────┴────────────┴────────────┴────────────┘  │
│                                                  │
GPT (GUID Partition Table):│  ┌─────┬──────┬──────┬──────┬───────┬─────┐     │
│  │ MBRGPT  │Part 1│Part 2...GPT │     │
│  │보호용│헤더  │      │      │       │백업 │     │
│  └─────┴──────┴──────┴──────┴───────┴─────┘     │
└──────────────────────────────────────────────────┘

블록 그룹 (ext4)

ext4는 디스크를 여러 블록 그룹으로 나누어 관리합니다.

┌────────────────────────────────────────────────────┐
│              ext4 파일 시스템 레이아웃               │
│                                                    │
│ ┌──────┬──────────┬──────────┬──────────┬────────┐ │
│ │Group │ Group 0Group 1Group 2...    │ │
│ │  0   │          │          │          │        │ │
│ └──────┴──────────┴──────────┴──────────┴────────┘ │
│                                                    │
│ 각 블록 그룹 내부:│ ┌────────┬────────┬────────┬────────┬────────────┐ │
│ │ SuperGroupBlock  │ inode  │ Data       │ │
│ │ BlockDesc.   BitmapTableBlocks     │ │
 (백업)Table+ inode │        │            │ │
│ │        │        │ Bitmap │        │            │ │
│ └────────┴────────┴────────┴────────┴────────────┘ │
└────────────────────────────────────────────────────┘

블록 그룹의 장점:

  • 지역성(Locality): 관련 데이터를 가까이 배치하여 디스크 탐색 최소화
  • 병렬 처리: 서로 다른 블록 그룹에 대한 작업을 병렬로 수행 가능
  • 안정성: 슈퍼블록과 그룹 디스크립터 백업으로 복구 가능

3. ext4 파일 시스템 내부 구조

ext4는 Linux에서 가장 널리 사용되는 파일 시스템입니다.

ext4 주요 특징

특성
최대 파일 크기16 TiB
최대 볼륨 크기1 EiB
최대 파일 이름 길이255 바이트
최대 디렉토리 깊이무제한
저널링지원 (ordered 기본)
익스텐트지원

익스텐트 (Extent) 기반 할당

ext4는 기존의 간접 블록 포인터 대신 익스텐트를 사용합니다.

기존 방식 (ext2/ext3):           ext4 익스텐트:
inode → 직접 포인터 12개         inode → 익스텐트 트리
     → 단일 간접 포인터
     → 이중 간접 포인터          익스텐트: (시작 블록, 길이)
     → 삼중 간접 포인터          하나의 익스텐트로 연속 블록 표현

: 100개 연속 블록              예: 100개 연속 블록
100개의 포인터 필요            → 1개의 익스텐트 (start=50, len=100)
// ext4 익스텐트 구조체 (간단화)
struct ext4_extent {
    uint32_t ee_block;     // 논리 블록 번호
    uint16_t ee_len;       // 블록 수 (최대 32768)
    uint16_t ee_start_hi;  // 물리 블록 상위 16비트
    uint32_t ee_start_lo;  // 물리 블록 하위 32비트
};

// 익스텐트 트리 헤더
struct ext4_extent_header {
    uint16_t eh_magic;     // 매직 넘버 (0xF30A)
    uint16_t eh_entries;   // 유효한 엔트리 수
    uint16_t eh_max;       // 최대 엔트리 수
    uint16_t eh_depth;     // 트리 깊이 (0 = 리프)
    uint32_t eh_generation;
};

ext4의 지연 할당 (Delayed Allocation)

전통적 방식:                     지연 할당:
write() 호출                     write() 호출
  │                                │
  ├→ 블록 할당 (즉시)              ├→ 페이지 캐시에 데이터 저장
  ├→ 디스크에 쓰기                    (블록 아직 미할당)
  └→ 완료                         │
                                   ├→ flush 시점
                                   │   ├→ 연속 블록 한번에 할당
                                   │   └→ 디스크에 쓰기
                                   └→ 완료

장점: 연속 블록 할당 가능성 증가, 성능 향상

4. Apple File System (APFS)

APFS는 Apple이 HFS+를 대체하기 위해 개발한 파일 시스템입니다.

APFS 주요 특징

┌──────────────────────────────────────────┐
APFS 컨테이너               │
│                                          │
│  ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│  │ Volume 1 │ │ Volume 2 │ │ Volume 3 │ │
 (macOS) (Data) (Preboot)│ │
│  └──────────┘ └──────────┘ └──────────┘ │
│                                          │
│  공간 공유: 볼륨들이 컨테이너 내         │
│  빈 공간을 동적으로 공유                  │
└──────────────────────────────────────────┘
  • Copy-on-Write (CoW): 데이터를 수정할 때 원본을 보존하고 새 위치에 기록
  • 스냅샷: CoW를 활용한 시점 복구 지원
  • 공간 공유: 하나의 컨테이너 내 여러 볼륨이 공간을 동적으로 공유
  • 암호화: 파일/볼륨 단위 네이티브 암호화 지원
  • 클론: 파일/디렉토리의 즉각적인 복사 (메타데이터만 복사, 수정 시 실제 복사)

Copy-on-Write 동작

초기 상태:
Block A[Original Data]

수정  (CoW):
Block A[Original Data]  (보존)
Block B[Modified Data]  (새 위치에 기록)
메타데이터 포인터가 Block B를 가리키도록 업데이트

스냅샷이 있으면:
스냅샷 → Block A (원본 참조 유지)
현재   → Block B (수정본 참조)

5. 성능 최적화

버퍼 캐시 (Buffer Cache)

애플리케이션 read() 요청
┌──────────────────┐
│   버퍼 캐시      │
 (커널 메모리)│                  │
[블록 42: data]  │ ← 캐시 히트: 즉시 반환
[블록 88: data][블록 15: data][블록 7:  data]└────────┬─────────┘
         │ 캐시 미스
    ┌─────────┐
    │  디스크  │ → 읽은 후 캐시에 저장
    └─────────┘

미리 읽기 (Read-Ahead)

순차 접근 패턴을 감지하면 다음 블록을 미리 읽어 캐시에 저장합니다.

요청 패턴: 블록 1 → 블록 2 → 블록 3...

블록 3 요청 시:
커널이 순차 패턴 감지 → 블록 4, 5, 6, 7도 미리 읽기

┌────┬────┬────┬────┬────┬────┬────┐
B1B2B3B4B5B6B7│요청│요청│요청│미리│미리│미리│미리│
│완료│완료│반환│읽기│읽기│읽기│읽기│
└────┴────┴────┴────┴────┴────┴────┘

Free-Behind

순차 읽기 시 이미 사용된 페이지를 캐시에서 제거하여 캐시 공간을 확보합니다.

순차 읽기 진행 방향 →

캐시 상태:
[B1] [B2] [B3] [B4] [B5]  ← 일반 LRU
 ↑ 오래된 페이지도 캐시에 남음

[--] [--] [B3] [B4] [B5]Free-Behind 적용
 ↑ 읽은 후 바로 해제 → 새 데이터를 위한 공간 확보

페이지 캐시와 버퍼 캐시의 통합 (Unified Buffer Cache)

과거 (분리):                    현재 (통합):
┌──────────┐ ┌──────────┐      ┌──────────────────────┐
│ 페이지   │ │ 버퍼     │      │    통합 페이지 캐시   │
│ 캐시     │ │ 캐시     │      │                      │
(mmap용)(read용)  │      │  mmap과 read/write   │
│          │ │          │      │  모두 같은 캐시 사용  │
└──────────┘ └──────────┘      └──────────────────────┘
 같은 데이터 중복 캐시 가능      중복 제거, 일관성 보장

6. NFS (Network File System)

NFS는 네트워크를 통해 원격 파일 시스템에 접근하는 분산 파일 시스템 프로토콜입니다.

NFS 아키텍처

클라이언트                           서버
┌──────────────────┐            ┌──────────────────┐
│ 사용자 프로세스   │            │                  │
open("/mnt/f")  │            │                  │
├──────────────────┤            │                  │
VFS         │            │                  │
├──────────────────┤            ├──────────────────┤
NFS 클라이언트  │            │  NFS 서버 데몬   │
  (nfsd)          │ ← RPC/XDR →│  (nfsd)├──────────────────┤            ├──────────────────┤
│    네트워크      │            │    로컬          │
    (TCP/UDP)     │            │    파일 시스템    │
└──────────────────┘            └──────────────────┘

NFS 마운트

# NFS 서버에서 공유 디렉토리 설정
# /etc/exports
/data  192.168.1.0/24(rw,sync,no_subtree_check)

# NFS 서비스 시작
sudo systemctl start nfs-server

# 클라이언트에서 마운트
sudo mount -t nfs server:/data /mnt/nfs

# /etc/fstab에 추가하여 부팅 시 자동 마운트
# server:/data  /mnt/nfs  nfs  defaults  0  0

NFS의 무상태(Stateless) 설계

NFS v3는 무상태 프로토콜로 설계되었습니다.

무상태 장점:
- 서버 충돌 후 재시작 시 클라이언트 재연결 불필요
- 서버가 클라이언트별 상태를 관리하지 않아 확장성 우수

무상태 구현:
- 파일 핸들(file handle)로 파일 식별
- 각 요청이 독립적 (오프셋 등 필요한 정보를 모두 포함)
- 캐싱은 클라이언트 측에서 처리

NFS v4 변화:
- 상태 유지(stateful) 프로토콜로 전환
- 파일 잠금, 위임(delegation) 등 고급 기능 지원
- 보안 강화 (Kerberos 인증)

7. 정리

  • 마운팅: 파일 시스템을 디렉토리 트리에 연결하는 과정
  • 블록 그룹: 데이터 지역성을 높이고 탐색 시간을 줄이는 구조
  • ext4: 익스텐트, 지연 할당, 저널링으로 성능과 안정성 확보
  • APFS: Copy-on-Write, 스냅샷, 공간 공유 등 현대적 기능
  • 성능 최적화: 버퍼 캐시, 미리 읽기, Free-Behind, 통합 페이지 캐시
  • NFS: RPC 기반 네트워크 파일 시스템, v3 무상태 / v4 상태 유지
퀴즈: 파일 시스템 내부 구조

Q1. ext4의 익스텐트(extent)가 기존 간접 블록 포인터보다 좋은 이유는 무엇인가요?

A1. 익스텐트는 연속된 물리 블록을 (시작 블록, 길이)로 표현하므로, 대용량 파일에서 수천 개의 개별 블록 포인터 대신 소수의 익스텐트로 관리할 수 있습니다. 이를 통해 메타데이터 오버헤드가 줄고, 연속 블록을 한 번의 I/O로 읽을 수 있어 성능이 향상됩니다.

Q2. Copy-on-Write(CoW)의 장점과 단점은 무엇인가요?

A2. 장점: 원본 데이터를 보존하므로 스냅샷 구현이 용이하고, 충돌 시 일관성을 유지합니다. 또한 파일 복제(clone)가 O(1)으로 빠릅니다. 단점: 수정 시 항상 새 위치에 기록하므로 순차 쓰기가 랜덤 쓰기로 변할 수 있고, 조각화가 발생할 수 있습니다.

Q3. NFS v3가 무상태 프로토콜인 이유와 v4에서 상태 유지로 전환한 이유는?

A3. v3의 무상태 설계는 서버 충돌 후 재시작이 간단하고 확장성이 좋습니다. 그러나 파일 잠금이나 캐시 일관성 등 고급 기능 구현이 어렵습니다. v4는 상태를 유지하여 파일 잠금, 위임(delegation), 보안 등 더 풍부한 기능을 지원하도록 발전했습니다.

[OS Concepts] 15. File-System Internals

File-System Internals

After examining the basic principles of file system implementation, we now take a deeper look at the internal structures and performance optimization techniques of real file systems. This article covers modern file systems such as ext4 and APFS, as well as network file systems including NFS.


1. File System Mounting

The operating system must mount a file system before using it. Mounting connects a file system to a specific point (mount point) in the directory tree.

Before mount:                  After mount:
     / (root)                      / (root)
    ╱    ╲                       ╱    ╲
  home   mnt                   home   mnt
 (empty)             │      │
 user1                        user1  ┌──────────────┐
USB drive    │
                                      (ext4)                                     │  photos/                                     │  docs/                                     └──────────────┘
                              Accessible via /mnt/photos
# 마운트 명령어 예시
# 장치를 마운트 포인트에 연결
mount /dev/sdb1 /mnt

# 특정 파일 시스템 타입 지정
mount -t ext4 /dev/sdb1 /mnt

# 읽기 전용 마운트
mount -o ro /dev/sdb1 /mnt

# 현재 마운트 목록 확인
mount | column -t

# 언마운트
umount /mnt

/etc/fstab File

Defines file systems to be automatically mounted at boot.

# /etc/fstab 예시
# 장치            마운트포인트  타입   옵션            덤프 패스
/dev/sda1         /            ext4   defaults         0    1
/dev/sda2         /home        ext4   defaults         0    2
/dev/sdb1         /data        xfs    noatime          0    2
tmpfs             /tmp         tmpfs  size=2G          0    0

2. Partitions and Block Groups

Disk Partition Structure

┌──────────────────────────────────────────────────┐
Physical Disk│                                                  │
│  ┌─────┬────────────┬────────────┬────────────┐  │
│  │ MBRPartition 1Partition 2Partition 3│  │
│  │      (ext4)      (swap)      (ext4)     │  │
│  │     │ /          │            │ /home      │  │
│  └─────┴────────────┴────────────┴────────────┘  │
│                                                  │
GPT (GUID Partition Table):│  ┌─────┬──────┬──────┬──────┬───────┬─────┐     │
│  │ MBRGPT  │Part 1│Part 2...GPT │     │
│  │prot.│header│      │      │       │bkup │     │
│  └─────┴──────┴──────┴──────┴───────┴─────┘     │
└──────────────────────────────────────────────────┘

Block Groups (ext4)

ext4 divides the disk into multiple block groups for management.

┌────────────────────────────────────────────────────┐
│              ext4 File System Layout│                                                    │
│ ┌──────┬──────────┬──────────┬──────────┬────────┐ │
│ │Group │ Group 0Group 1Group 2...    │ │
│ │  0   │          │          │          │        │ │
│ └──────┴──────────┴──────────┴──────────┴────────┘ │
│                                                    │
Inside each block group:│ ┌────────┬────────┬────────┬────────┬────────────┐ │
│ │ SuperGroupBlock  │ inode  │ Data       │ │
│ │ BlockDesc.   BitmapTableBlocks     │ │
 (bkup)Table+ inode │        │            │ │
│ │        │        │ Bitmap │        │            │ │
│ └────────┴────────┴────────┴────────┴────────────┘ │
└────────────────────────────────────────────────────┘

Benefits of block groups:

  • Locality: Places related data close together to minimize disk seeks
  • Parallelism: Operations on different block groups can be performed in parallel
  • Reliability: Superblock and group descriptor backups enable recovery

3. ext4 File System Internals

ext4 is the most widely used file system on Linux.

ext4 Key Features

PropertyValue
Max file size16 TiB
Max volume size1 EiB
Max file name length255 bytes
Max directory depthUnlimited
JournalingSupported (ordered)
ExtentsSupported

Extent-Based Allocation

ext4 uses extents instead of traditional indirect block pointers.

Traditional (ext2/ext3):          ext4 Extents:
inode → 12 direct pointers       inode → extent tree
     → single indirect
     → double indirect           extent: (start block, length)
     → triple indirect           one extent represents contiguous blocks

Ex: 100 contiguous blocks        Ex: 100 contiguous blocks
100 pointers needed            → 1 extent (start=50, len=100)
// ext4 익스텐트 구조체 (간단화)
struct ext4_extent {
    uint32_t ee_block;     // 논리 블록 번호
    uint16_t ee_len;       // 블록 수 (최대 32768)
    uint16_t ee_start_hi;  // 물리 블록 상위 16비트
    uint32_t ee_start_lo;  // 물리 블록 하위 32비트
};

// 익스텐트 트리 헤더
struct ext4_extent_header {
    uint16_t eh_magic;     // 매직 넘버 (0xF30A)
    uint16_t eh_entries;   // 유효한 엔트리 수
    uint16_t eh_max;       // 최대 엔트리 수
    uint16_t eh_depth;     // 트리 깊이 (0 = 리프)
    uint32_t eh_generation;
};

ext4 Delayed Allocation

Traditional approach:                Delayed allocation:
write() call                         write() call
  │                                    │
  ├→ Allocate blocks (immediately)     ├→ Store data in page cache
  ├→ Write to disk                        (blocks not yet allocated)
  └→ Done                                       ├→ At flush time
                                       │   ├→ Allocate contiguous blocks at once
                                       │   └→ Write to disk
                                       └→ Done

Advantage: Increased chance of contiguous allocation, better performance

4. Apple File System (APFS)

APFS is Apple's file system developed to replace HFS+.

APFS Key Features

┌──────────────────────────────────────────┐
APFS Container│                                          │
│  ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│  │ Volume 1 │ │ Volume 2 │ │ Volume 3 │ │
 (macOS) (Data) (Preboot)│ │
│  └──────────┘ └──────────┘ └──────────┘ │
│                                          │
Space sharing: Volumes dynamically      │
│  share free space within the container   │
└──────────────────────────────────────────┘
  • Copy-on-Write (CoW): Preserves the original and writes to a new location when modifying data
  • Snapshots: Point-in-time recovery using CoW
  • Space Sharing: Multiple volumes within a single container share space dynamically
  • Encryption: Native encryption at file/volume level
  • Clones: Instant file/directory copy (copies only metadata, actual copy on modification)

Copy-on-Write Operation

Initial state:
Block A[Original Data]

On modification (CoW):
Block A[Original Data]  (preserved)
Block B[Modified Data]  (written to new location)
Metadata pointer updated to point to Block B

With a snapshot:
SnapshotBlock A (retains original reference)
CurrentBlock B (modified version reference)

5. Performance Optimization

Buffer Cache

Application read() request
┌──────────────────┐
Buffer Cache (Kernel Memory)│                  │
[Block 42: data] │ ← Cache hit: return immediately
[Block 88: data][Block 15: data][Block 7:  data]└────────┬─────────┘
Cache miss
    ┌─────────┐
Disk   │ → Read and store in cache
    └─────────┘

Read-Ahead

When a sequential access pattern is detected, the next blocks are read into the cache in advance.

Request pattern: Block 1Block 2Block 3...

When Block 3 is requested:
Kernel detects sequential pattern → also reads blocks 4, 5, 6, 7

┌────┬────┬────┬────┬────┬────┬────┐
B1B2B3B4B5B6B7│req │req │req │read│read│read│read│
│done│done│ret │ahd │ahd │ahd │ahd │
└────┴────┴────┴────┴────┴────┴────┘

Free-Behind

During sequential reads, evicts already-used pages from the cache to free space.

Sequential read direction →

Cache state:
[B1] [B2] [B3] [B4] [B5]Normal LRU
Old pages remain in cache

[--] [--] [B3] [B4] [B5]Free-Behind applied
Released after read → space for new data

Unified Buffer Cache

Past (separate):                 Present (unified):
┌──────────┐ ┌──────────┐      ┌──────────────────────┐
Page     │ │ Buffer   │      │  Unified Page CacheCache    │ │ Cache    │      │                      │
(for mmap)(for read)│      │  Both mmap and       │
│          │ │          │      │  read/write use the  │
└──────────┘ └──────────┘      │  same cache          │
 Same data may be              └──────────────────────┘
 cached twice                   No duplication,
                                consistency guaranteed

6. NFS (Network File System)

NFS is a distributed file system protocol for accessing remote file systems over a network.

NFS Architecture

Client                              Server
┌──────────────────┐            ┌──────────────────┐
User Process     │            │                  │
open("/mnt/f")  │            │                  │
├──────────────────┤            │                  │
VFS         │            │                  │
├──────────────────┤            ├──────────────────┤
NFS Client      │            │  NFS Server  (nfsd)          │ ← RPC/XDR →│  Daemon (nfsd)├──────────────────┤            ├──────────────────┤
Network       │            │    Local    (TCP/UDP)     │            │    File System└──────────────────┘            └──────────────────┘

NFS Mount

# NFS 서버에서 공유 디렉토리 설정
# /etc/exports
/data  192.168.1.0/24(rw,sync,no_subtree_check)

# NFS 서비스 시작
sudo systemctl start nfs-server

# 클라이언트에서 마운트
sudo mount -t nfs server:/data /mnt/nfs

# /etc/fstab에 추가하여 부팅 시 자동 마운트
# server:/data  /mnt/nfs  nfs  defaults  0  0

NFS Stateless Design

NFS v3 was designed as a stateless protocol.

Stateless advantages:
- No client reconnection needed after server restart
- Server doesn't manage per-client state, good scalability

Stateless implementation:
- File handle identifies files
- Each request is independent (includes all needed info like offset)
- Caching handled on the client side

NFS v4 changes:
- Switched to stateful protocol
- Supports advanced features like file locking, delegation
- Enhanced security (Kerberos authentication)

7. Summary

  • Mounting: The process of attaching a file system to the directory tree
  • Block Groups: Structure that improves data locality and reduces seek time
  • ext4: Performance and reliability through extents, delayed allocation, and journaling
  • APFS: Modern features including Copy-on-Write, snapshots, and space sharing
  • Performance Optimization: Buffer cache, read-ahead, free-behind, unified page cache
  • NFS: RPC-based network file system, v3 stateless / v4 stateful
Quiz: File-System Internals

Q1. Why are ext4 extents better than traditional indirect block pointers?

A1. Extents represent contiguous physical blocks as (start block, length), so instead of thousands of individual block pointers for large files, they can be managed with a small number of extents. This reduces metadata overhead and improves performance by reading contiguous blocks in a single I/O operation.

Q2. What are the advantages and disadvantages of Copy-on-Write (CoW)?

A2. Advantages: Original data is preserved, making snapshot implementation easy and maintaining consistency on crashes. File cloning is also O(1) fast. Disadvantages: Modifications always write to new locations, which can turn sequential writes into random writes and may cause fragmentation.

Q3. Why was NFS v3 stateless, and why did v4 switch to stateful?

A3. The stateless design of v3 makes server restart after crashes simple and provides good scalability. However, it makes advanced features like file locking and cache consistency difficult to implement. v4 maintains state to support richer features such as file locking, delegation, and security.