Skip to content
Published on

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

Authors

파일 시스템 내부 구조

파일 시스템 구현의 기본 원리를 살펴본 후, 이제 실제 파일 시스템의 내부 구조와 성능 최적화 기법을 더 깊이 알아봅니다. 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), 보안 등 더 풍부한 기능을 지원하도록 발전했습니다.