운영체제 학습 노트 목차

파일 시스템 — 디스크를 이름으로 다루다

디스크는 사실 번호가 매겨진 블록들의 거대한 배열일 뿐이다 — "3829번 섹터에 써라" 같은 식이다. 그런데 우리는 /home/user/report.txt라는 이름으로 읽고 쓴다. 이 블록 덩어리를 이름·디렉터리·권한을 가진 파일로 추상화하는 게 파일 시스템이다. OS의 추상화 중에서도 — *영구 저장(persistence)*을 다루기에, 전원이 갑자기 나가도 데이터가 망가지지 않게 하는 게 핵심 과제다. 그 추상과 무결성 보장을 본다.

파일은 무엇으로 이뤄지나 — inode와 디렉터리

파일 하나는 데이터만이 아니라 메타데이터도 갖는다 — 크기, 소유자, 권한, 수정 시각, 그리고 실제 데이터가 디스크의 어느 블록에 있는지. 이 메타데이터를 담는 게 inode다. 흥미롭게도 — 파일 이름은 inode에 없다. 이름은 디렉터리가 갖는데, 디렉터리란 사실 "이름 → inode 번호" 매핑의 표다.

다이어그램 로딩 중…

이 분리 덕에 한 파일에 여러 이름(하드 링크)을 줄 수 있고, 이름을 바꿔도 데이터는 그대로다(inode는 안 변하니까).

전원이 갑자기 나가면 — 크래시 일관성과 저널링

여기서 영구 저장의 어려움이 드러난다. 파일 하나를 만드는 것조차 — 디렉터리에 항목 추가 + inode 초기화 + 빈 블록 비트맵 갱신, 즉 디스크의 여러 곳을 써야 한다. 그런데 그 중간에 전원이 나가면?디렉터리는 파일을 가리키는데 inode는 비어 있거나, 블록은 쓰였다고 표시됐는데 어느 파일도 안 가리키는 불일치가 남는다. (출처: Crash Consistency.)

해법이 **저널링(journaling)**이다 — *실제 위치에 쓰기 전에, "이러이러하게 바꾸겠다"를 먼저 *저널(로그)에 기록하고, 저널이 안전히 쓰인 뒤 실제 구조를 갱신한다. 만약 중간에 죽으면 — 재부팅 때 *저널을 다시 적용(redo)*해 일관성을 회복한다.

왜 이게 보편적인가 — "실제 변경 전에 의도를 로그에 먼저 기록한다"는 **선행 기록 로그(write-ahead log, WAL)**는 파일 시스템만의 것이 아니다. 데이터베이스의 트랜잭션 로그(그래서 DB가 죽어도 커밋된 트랜잭션을 복구)도, 로그 기반 메시지 시스템도 같은 원리다. 원자적으로 못 하는 여러 단계를, 로그에 먼저 한 줄로 기록해 *"전부 되거나 전부 안 되거나"*를 흉내 내는 것 — 이것이 영속성과 신뢰성의 보편적 기법이다.

디스크는 느리다 — 페이지 캐시

디스크는 메모리보다 수만 배 느리다. 그래서 OS는 읽은 디스크 블록을 메모리(페이지 캐시)에 보관해 — 다음에 같은 걸 읽으면 디스크 대신 메모리에서 준다. 쓰기도 일단 페이지 캐시에 모았다가 나중에 디스크로(write-back) 내보내 빠르게 응답한다. 다만 — write-back은 위험하다. 캐시에만 있고 디스크에 안 내려간 데이터는 전원이 나가면 사라진다. 그래서 반드시 보존돼야 할 데이터는 **fsync**로 *"지금 디스크에 강제로 내려라"*를 호출한다(DB가 커밋 시 fsync로 내구성을 보장하는 게 이것이다). 그리고 여러 종류의 파일 시스템(ext4·XFS·NFS…)을 *같은 인터페이스(open/read/write)*로 쓰게 해 주는 게 VFS(가상 파일 시스템) — 또 하나의 추상화 계층이다.

왜 빠른가 — 이 페이지 캐시가 고성능 저장·전송 시스템의 비결이다. 디스크에 순차로 쓰되, 읽는 쪽이 따라잡고 있으면 페이지 캐시에서 바로 내보내면(디스크를 안 읽음) 엄청나게 빨라진다 — 다음 편에서 볼 zero-copy가 이 페이지 캐시를 네트워크로 직행시키는 기법이다. 작은 I/O를 버퍼에 모아 시스템 콜·디스크 접근을 줄이는 버퍼링도 같은 발상이다.

정리하면, 파일 시스템은 번호 매겨진 블록을 이름·메타데이터를 가진 파일로 추상화한다 — inode가 메타데이터·블록 위치를, 디렉터리가 이름→inode 매핑을 갖는다. 영구 저장의 핵심 과제는 크래시 일관성인데, *저널링(WAL)*으로 실제 변경 전에 로그를 먼저 써 복구 가능하게 한다(DB 트랜잭션 로그와 같은 원리). 느린 디스크는 페이지 캐시로 가리되 내구성은 fsync로 보장하고(zero-copy의 토대), VFS로 여러 파일 시스템을 한 인터페이스로 묶는다. 파일이 저장된 데이터라면 — 장치와 데이터를 실제로 주고받는 법, I/O가 다음이다.

메모리 관리 — 단편화·교체·스래싱·OOMI/O — 폴링/인터럽트·DMA·blocking/async