한양과학기술고등학교

에듀테크 프로젝트 대시보드

파일 시스템과 inode

🗂️ 파일 시스템과 inode

파일의 이름은 디렉터리에 있고, 파일의 실체(크기·권한·데이터 위치)는 inode 라는 구조체에 있다. 이름과 실체가 분리돼 있기 때문에 하드 링크, rm 의 동작, mv 가 빠른 이유가 전부 설명된다. 직접 만져 보자.

1 디렉터리는 "이름 → inode 번호" 표일 뿐이다

디렉터리 자체도 하나의 파일이고, 그 내용은 (파일 이름, inode 번호) 쌍의 목록이다. 파일을 열면 커널은 ① 디렉터리에서 이름으로 inode 번호를 찾고 → ② inode 테이블에서 그 번호의 inode를 읽어 → ③ inode 안의 블록 포인터를 따라 실제 데이터 블록을 읽는다.

inode에는 파일 이름이 없다. 그래서 한 inode에 여러 이름을 붙일 수 있고(하드 링크), 이름을 바꿔도 데이터는 1바이트도 안 움직인다(디렉터리 표의 문자열만 교체).

2 미니 파일 시스템 — 만들고, 링크하고, 지우기

inode 8칸, 데이터 블록 24칸짜리 디스크다. 이름과 크기를 정해 파일 생성을 누르고, 디렉터리 행을 클릭해 선택한 뒤 하드 링크/심볼릭 링크/삭제를 눌러 본다. 블록이 4개를 넘으면 간접 블록(주황 테두리) 하나가 추가로 소비된다.

이름
블록 2

디렉터리  (이름 → inode)

이름inode종류

inode 테이블

데이터 블록  (색 = 소유 inode · 주황 점선 = 간접 블록)

디렉터리에서 항목을 클릭하면 해당 inode의 내부가 여기 표시됩니다.
0
사용 중 inode
0 / 24
데이터 블록
0
디렉터리 엔트리
0
해제된 블록(누적)

3 하드 링크 vs 심볼릭 링크

하드 링크 (ln a b)심볼릭 링크 (ln -s a b)
가리키는 것같은 inode 번호대상의 경로 문자열
자기 inode없음 (이름만 추가)따로 있음 (내용 = 경로)
원본 삭제 시링크 수만 감소, 데이터 유지깨진 링크(dangling)
디렉터리 대상불가 (루프 방지)가능
다른 파티션불가 (inode 번호는 파티션 내부용)가능

rm 은 파일을 지우는 게 아니라 디렉터리 엔트리 하나를 지우고 링크 수(link count) 를 1 줄인다. 링크 수가 0 이 되고, 그 파일을 열어 둔 프로세스도 없을 때 비로소 inode와 데이터 블록이 해제된다. 그래서 실행 중인 로그 파일을 rm 해도 프로세스가 계속 쓸 수 있다.

4 블록 포인터 — 작은 파일도, 큰 파일도

inode 안의 포인터 배열은 크기가 고정이다(예: 직접 12개). 파일이 그보다 커지면 간접 블록을 한 칸 할당해 그 안에 "블록 번호 목록"을 채운다. 더 커지면 2중·3중 간접까지 간다. 덕분에 작은 파일은 추가 블록 없이 빠르고, 큰 파일도 inode 크기를 늘리지 않고 담는다.

단계담을 수 있는 양 (블록 4KB 기준, 대략)
직접 포인터 12개48 KB
1중 간접 (포인터 1024개)+ 4 MB
2중 간접+ 4 GB
3중 간접+ 4 TB

5 뼈대 — inode 구조체와 이름 해석

// 파일 이름은 여기 없다. 이름은 디렉터리 엔트리에 있다.
struct inode {
    uint16_t mode;          // 파일/디렉터리/심링크 + 권한(rwx)
    uint16_t uid, gid;
    uint32_t size;          // 바이트 단위 파일 크기
    uint32_t atime, mtime, ctime;
    uint16_t links_count;   // 이 inode를 가리키는 이름의 개수
    uint32_t block[15];      // 0~11: 직접, 12: 1중, 13: 2중, 14: 3중 간접
};

struct dirent { uint32_t inode_no; char name[]; };

// open("/home/a.txt") 의 이름 해석(path walk)
int namei(const char *path) {
    int ino = ROOT_INO;                 // '/' 는 항상 2번
    for (char *part = strtok(path,"/"); part; part = strtok(NULL,"/")) {
        ino = dir_lookup(ino, part);     // 디렉터리에서 이름으로 검색
        if (ino < 0) return -ENOENT;
    }
    return ino;
}

ls -i 로 inode 번호를, stat 으로 링크 수(Links:)와 블록 수를 볼 수 있다. df -i 는 디스크 용량이 아니라 inode 잔여 개수를 보여 준다 — 작은 파일을 수백만 개 만들면 용량이 남아도 inode가 먼저 바닥나 "No space left" 가 뜬다.