Home 모던 리눅스 교과서 5. 파일 시스템
Post
Cancel

모던 리눅스 교과서 5. 파일 시스템

  • 리눅스의 대부분의 요소들은 파일로 이루어져있다.
  • 대부분의 것들을 파일로 관리함으로써 표준화되고 통일된 인터페이스를 제공한다.

기본 개요

  • 파일 시스템 용어에 대해 알아보기 전에 파일 시스템에 대해 암묵적으로 가지고 있던 가정과 예측을 정리한다.
  • 예외가 있긴 하지만 오늘날 사용되는 대부분의 파일시스템은 계층 구조로 되어 있다.
    • 즉 사용자는 보통 root(/)로 시작하는 단일 파일 시스템 트리를 제공받게 된다.
  • 파일 시스템 트리에는 디렉터리와 파일이라는 두 가지 유형의 객체가 있다. 디렉터리를 파일을 그룹화 할 수 있는 조직의 단위라고 생각하자.
  • 일반적으로 파일 시스템은 커널에서 구현된다.
  • 알아둬야 할 용어는 다음과 같다.
    • 드라이브 : HDD 또는 SDD와 같은 (물리적) 블록 디바이스다. 가상 머신의 드라이브는 에뮬레이션 될 수도 있다.
  • 파티션 : 드라이브를 스토리지 섹터의 집합인 파티션으로 논리적으로 분할 할 수 있다.
  • 볼륨 : 파티션과 비슷하지만 더 유연하며, 특정 파일시스템용으로 포맷되기도 한다.
  • 슈퍼 블록 : 시스템이 포맷되면 파일 시스템의 시작 부분에 파일 시스템의 메타데이터를 캡처하는 특수 섹션이 생긴다. 여기에는 파일 시스템의 유형, 블록, 상태, 블록당 inode 수 등이 담긴다.
  • 아이노드 : 파일 시스템의 아이노드는 크기, 소유자, 위치, 날짜, 권한과 같은 파일의 메타데이터를 저장하지만 파일명과 실제 데이터는 저장하지 않는다. 이 데이터는 디렉터리에 보관되며, 디렉터리는 아이노드를 파일명에 매핑하는 특별한 종류의 일반 파일이라고 할 수 있다.
  • 저수준의 파일시스템과 블록 디바이스 명령 모음
명령어사용 예제
lsblk모든 블록 디바이스 나열
fdisk, parted디스크 파티션 관리
blkidUUID와 같은 블록 디바이스 속성 표시
hwinfo하드웨어 정보 표시
file -s파일시스템과 파티션 정보 표시
stat, df -i, ls -i아이노드와 관련된 정보 표시 및 목록 출력
  • 파일시스템과 관련해 앞으로 접하게 될 또 다른 용어는 link 이다.
    • 다른 이름의 파일을 참조하거나 shortcut을 제공하고 싶을 때 활용된다.
    • hard link : 아이노드를 참조하며 디렉터리는 참조할 수 없다. 또한 파일 시스템이 서로 다르면 동작하지 않는다.
    • symbolic link 또는 symlink : 파일의 내용이 다른 파일의 경로를 나타내는 특수 파일이다. ```bash ln myfile somealias # 하드 링크 생성 ln -s myfile somesoftalias # 소프트 링크 생성

ls -al *alias stat somealias stat somesoftalias

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
# 가상 파일 시스템(VFS)
- 리눅스는 가상 파일시스템이라는 추상화를 통해 다양한 종류의 리소스(인메모리, 로컬 연결, 네트워크 스토리지)에 파일과 유사한 접근을 제공할 수 있다.
- 기본 개념은 클라이언트(system call)와 개별 파일 시스템 사이에 간접 계층을 도입하는 것이다.
- 여기서 개별 파일시스템은 구체적인 디바이스 또는 다른 리소스 유형을 위한 연산을 구현한다.
  - 즉 VFS는 일반 작업(열기, 읽기, 찾기)을 실제 구현 세부사항과 분리한다.
- VFS는 파일 체계를 기반으로 클라이언트가 동일한 방법으로 리소스에 접근할 수 있게 해주는 커널의 추상화 계층이다.
- 리눅스의 파일에는 규정된 구조가 없다. 그저 바이트 스트림일 뿐이다.
- 바이트의 의미를 결정하는 것은 클라이언트에게 달려 있다. 그림에서 볼 수 있듯이 VFS는 다양한 종류의 파일시스템에 대한 접근을 추상화한다.
## 파일 시스템 종류
![VFS](/assets/img/2024-06-24-modern-linux-5/vfs-hierarchy.png)
### ext3, XFS, FAT, NTFS 같은 로컬 파일 시스템
- 이런 파일 시스템은 드라이버를 사용하여 HDD나 SSD와 같은 로컬 블록 디바이스에 접근한다.
### 장기 저장 디바이스가 지원하지 않지만 주 메모리(RAM)에 상주하는 tmpfs와 같은 인메모리 파일 시스템
- 아래에 다룰 예정
### procfs 같은 의사 파일시스템
- 이런 파일 시스템도 본질적으로는 인메모리다. 커널 인터페이스와 디바이스 추상화에 사용된다.
### NFS, 삼바(Samba), 넷웨어(Netware) 등의 네트워크 파일 시스템
- 이런 파일 시스템도 드라이버를 사용한다. 하지만 실제 데이터가 상주하는 저장 디바이스는 로컬이 아니라 원격으로 연결되어 있다.
- 이는 드라이버에 네트워크 작업이 포함됨을 의미하므로 추후 네트워크 장에서 다룬다.
- VFS의 구성을 설명하기는 쉽지 않지만 파일과 관련된 시스템 콜은 100개가 넘는다.
  - 하지만 그 핵심은 아래와 같이 몇가지 카테고리로 그룹화 할 수 있다.

| 카테고리    | 시스템 콜 예시                               |
| ----------- | -------------------------------------------- |
| 아이노드    | chmod, chown, stat                           |
| 파일        | open, close, seek, truncate, read, write     |
| 디렉터리    | chdir, getcwd, link, unlink, rename, symlink |
| 파일 시스템 | mount, flush, chroot                         |
| 그 외       | mmap, poll, sync, flock                      |

- 다양한 VFS 시스템 콜이 파일시스템 구현으로 보내진다. 그 밖의 시스템 콜은 VFS의 기본 구현으로 전달된다.
- 리눅스 커널은 관련 VFS 데이터 구조(include/linux/fs.h)를 다음과 같이 정의 한다.
  - **inode** : 핵심 파일시스템 객체, 캡처 유형, 소유권, 권한, 링크, 파일 테이터를 포함하는 블록에 대한 포인터, 생성과 접근 통계
  - **file** : 열려 있는 파일을 나타냄(path, 현재 위치와 아이노드 포함)
  - **dentry(디렉터리 항목)** : 부모와 자식 저장
  - **super_block** : 마운트 정보를 포함한 파일시스템을 나타냄
  - **그 외** : vfsmount와 file_system_type 포함

## 논리 볼륨 관리자
- 앞서 파티션을 사용해 드라이브를 분할하는 방법에 대해 이야기 했다.
- 하지만 파티션은 특히 (저장 공간 양을 변경하기 위한) 크기 조정이 필요할 때 사용하기 어렵다.
- 논리 볼륨 관리자(LVM)는 파일시스템과 물리 개체 간의 간접 계층을 사용한다.
- 이렇게 하면 리소스 풀링을 통해 위험이 없고 중단 시간도 없는 확장과 자동 스토리지 증설이 가능해진다.
![LVM](/assets/img/2024-06-24-modern-linux-5/LVM.png)
- **물리 볼륨(PV)** : 디스크 파티션, 전체 디스크 드라이브, 기타 드라이브 등이 있다.
- **논리 볼륨(LV)** : 볼륨 그룹에서 생성된 블록 디바이스. 이들은 개념적으로 파티션과 비슷하다. 논리 볼륨을 사용하려면 먼저 논리 볼륨에 파일 시스템을 생성해야 한다. 사용 중에 논리 볼륨의 크기를 쉽게 조정할 수 있다.
- **볼륨 그룹(VG)** : 물리 볼륨과 논리 볼륨 사이의 중개자. 볼륨 그룹이란 공동으로 리소스를 제공하는 물리 볼륨 풀이라고 생각하면 된다.

### LVM 관리 도구
- LVM으로 볼륨을 관리하려면 여러 도구가 필요하지만, 대부분 이름이 직관적이며 사용하기도 비교적 쉽다.
- **PV 관리 도구**
  - `lvmdiskscan`
  - `pvdisplay`
  - `pvcreate`
  - `pvscan`
- **볼륨 그룹 관리 도구**
  - `vgs`
  - `vgdisplay`
  - `vgcreate`
  - `vgextend`
- 논리 볼륨 관리 도구
  - `lvs`
  - `lvscan`
  - `lvcreate`

## 파일 시스템 작업
- 파티션이나 논리 볼륨에서 파일 시스템을 생성하는 방법에 대해 설명한다.
- 이에 관해 2가지 단계가 있다.
  1. 파일 시스템을 생성(리눅스가 아닌 다른 운영체제에서는 이 단계를 포맷이라고도 함)한
  2. 이를 마운트 한다.
### 파일 시스템 생성
- 파일 시스템을 사용하기 위한 첫 번째 단계는 파일시스템 생성이다.
- 즉 파티션이나 볼륨을 입력으로 받아 시스템을 구성하는 관리적인 부분을 설정해야 한다.
- mkfs를 사용하여 파일 시스템을 구축할 수 있다.
- mkfs는 두 가지 기본 입력을 받는다.
  - 하나는 생성하려는 파일 시스템 유형
  - 다른 하나는 파일 시스템을 생성하려는 디바이스이다.
```bash
mkfs -t ext4 \ # ext4 유형의 파일 시스템을 생성한다.
  /dev/some_vg/some_lv # 논리 볼륨 /dev/some_vg/some_lv에 파일 시스템을 생성한다.

(생각보다 별 게 없다.)

  • mkfs로 파일 시스템을 만든 후에는 파일 시스템 트리에서 사용할 수 있게 만들어줘야 한다.

파일시스템 마운트

  • 파일 시스템을 마운트한다는 말은 파일 시스템 트리(/에서 시작)에 이를 연결함을 의미한다.
  • mount 명령으로 파일시스템을 연결한다. mount는 두 가지 주 입력을 받는다.
    • 하나는 연결하려는 디바이며 다른 하나는 파일시스템 트리 내의 위치이다.
    • 또한 다른 입력값도 제공할 수 있는데, 읽기 전용을 위한 마운트 옵션(-o)을 사용하거나 파일시스템 트리에 디렉터리를 마운트하기 위한 바인드 마운트(–bind) 등을 사용할 수 있다.
      1
      
      mount -t ext4, tmpfs #마운트 목록을 출력하지만 특정 파일시스템 유형만 표시한다(여기서는 ext4, tmpfs)
      
  • 이때, 생성된 파일시스템 유형으로 마운트됐는지를 반드시 확인해야 한다.
    • 예를 들어 mount -t vfat /dev/sdX2 /media를 사용해 SD카드를 마운트하려는 경우 해당 SD 카드가 vfat로 포맷됐는지 여부를 알아야 한다.
  • 마운트는 시스템이 실행되는 동안에만 유효하므로 영구적으로 유지하려면 fstab(/etc/fstab) 파일을 사용해야 한다.

범용 파일시스템 레이아웃

  • 파일 시스템이 준비되고 나서 다음으로 풀어야 할 과제는 그 내용을 구조화할 방법을 찾는 것이다.
  • 프로그램이 저장된 위치, 구성 데이터, 시스템 데이터, 사용자 데이터와 같은 항목을 구조화할 수 있다.
  • 이런 디렉터리의 구성과 내용을 파일시스템 레이아웃 이라고 부른다. 공식적으로 이런 레이아웃은 파일시스템 계층구조 표준(Filesystem Hierarchy Standard, FHS)라고 한다.
    • FHS는 구조와 내부에 들어갈 권장 파일 목록을 포함해 디렉토리를 정의한다.
  • 흔히 쓰이는 디렉터리 목록은 아래와 같다.
디렉터리의미
bin, sbin시스템 프로그램과 명령
boot커널 이미지와 관련 구성 요소
dev디바이스(터미널, 드라이브 등)
etc시스템 구성 파일
home사용자 홈 디렉터리
lib공유시스템 라이브러리
mnt, media이동식 미디어용 마운트 지점
opt배포판 지정 디렉터리, 패키지 관리자 파일을 호스팅할 수 있다
proc, sys커널 인터페이스
tmp임시 파일용
usr사용자 프로그램(일반적으로 읽기 전용)
var사용자 프로그램(로그, 백업, 네트워크 캐시 등)

의사 파일시스템(pseudo filesystem)

  • VFS 구현자(implementor)가 블록 디바이스가 아닌 경우(SSD 드라이브 또는 SD 카드) 인터페이스를 어떻게 제공하는지 알아본다.
  • 의사 파일시스템은 파일시스템인 것처럼 가장하여 일반적인 방식(ls, cd, cat)으로 상호 작용할 수 있지만, 실제로는 커널 인터페이스를 래핑한 것이다.
    • 프로세스에 대한 정보
    • 키보드 같은 디바이스와의 상호 작용
    • 데이터 소스나 싱크로 사용할 수 있는 특수 디바이스 같은 유틸리디
  • 리눅스의 세 가지 주요 의사파일 시스템은 다음과 같다.

    procfs

  • 해당 파일에서는 일반적으로 아래와 같은 두 가지 유형의 정보를 찾을 수 있다.
    • /proc/PID/의 프로세스별 정보. 이는 커널이 디렉터리를 통해 제공하는 프로세스 관련 정보로, PID를 디렉터리 이름으로 사용한다.
    • 마운트, 네트워크 관련 정보, TTY 드라이버, 메모리 정보, 시스템 버전, 가동 시간과 같은 기타 정보
  • cat 등의 명령을 사용하면 아래와 같은 프로세스별 정보를 간단히 쉽할 수 있다.
항목유형정보
attr디렉터리보안 속성
cgroup파일제어 그룹
cmdline파일커맨드라인
cwd링크현재 작업 디렉터리
environ파일환경변수
exe링크프로세스 실행 파일
fd디렉터리파일 디스크립터
io파일스토리지 I/O(바이트/문자 읽기 쓰기)
limits파일리소스 한계
mem파일사용된 메모리
mounts파일사용된 마운트
net디렉터리네트워크 통계
stat파일프로세스 상태
syscall파일시스템 콜 사용량
task디렉터리작업별(스레드별) 정보
timers파일타이머 정보
  • 예시 : 현재 프로세스에 대한 ARP 정보 수집
    1
    
    cat /proc/self/net/arp
    
  • procfs는 저수준 디버깅이나 시스템 도구 개발에 유용하다.
  • 상대적으로 지저분하기 때문에 각 파일이 나타내는 내용과 그 안에 있는 정보를 해석하는 방법을 이해하려면 커널 문서가 필요하며, 커널 소스 코드가 있으면 더 좋다.

sysfs

  • procfs에 비해 커널이 표준화된 레이아웃을 사용하여 선택한 정보를 노출하는 리눅스 고유의 구조화된 방법이다.
  • 디렉터리 설명은 아래와 같다.
    • block/ : 발견된 블록 디바이스의 심볼릭 링크
    • bus/ : 커널에서 지원하는 각 물리 버스 유형마다 한 개씩 하위 디렉터리가 있다.
    • class/ : 디바이스 클래스가 포함되어 있다.
    • dev/ : 두 개의 하위 디렉터리가 포함되어 있다. 블록 디바이스용과 시스템의 문자 디바이스 용이 있으며, 이는 major-ID:minor-ID로 구성된다.
    • devices/ : 커널은 디바이스를 트리 형태로 표현한 정보를 제공한다.
    • firmware/ : 펌웨어 관련 속성을 관리할 수 있다.
    • fs/ : 일부 파일시스템의 하위 디렉터리가 포함되어 있다.
    • module/ : 이 디렉터리에서 커널에 로드된 각 모듈의 하위 디렉터리를 찾을 수 있다.
    • 이외에 더 많다.
  • procfs에서 제공하는 일부 정보가 sysfs에서 제공하는 것과 일부 중복되지만, 메모리 정보 같은 것은 procfs에서만 제공된다.
    1
    
    ls -al /sys/block/sda/ | head -7
    

devfs

  • devfs는 물리적 디바이스에서부터 난수 생성기나 쓰기 전용 데이터 싱크에 이르기까지 모든 디바이스를 나타내는 디바이스 특수 파일을 호스팅한다.
  • devfs를 통해 사용 가능하고 관리되는 디바이스는 다음과 같다.
    • 블록 디바이스 : 저장 디바이스(드라이브) 같은 블록의 데이터 처리
    • 문자 디바이스 : 터미널, 키보드, 마우스 같은 디바이스를 문자 단위로 처리한다.
    • 특수 디바이스 : 데이터를 생성하거나 조작할 수 있다.
  • 예시 : 임의의 문자열을 얻고 싶을 때
    1
    
    tr -dc A-Za-z0-9 < /dev/urandom | head -c 42
    

일반 파일

  • 오피스 문서, YAML, JSON, 이미지 등등의 파일 등이 모두 이 범주에 속한다.

범용 파일 시스템

  • 리눅스 배보판에서 사용되는 기본 값이나 이동식 디바이스 같은 저장 디바이스 에서 널리 사용되는 파일 시스템을 포괄하는 말이다.
  • 종류
    • ext4 : 오늘날 많은 배포판에서 기본적으로 널리 사용되는 파일 시스템이다.
      • 저널링 기능을 제공하기 때문에 변경 사항이 로그에 기록되어 최악의 경우가 닥쳤을 때 복구가 빠르다.
      • 범용으로 사용하기에 좋은 선택지이다.
    • XFS : 대용량 파일과 고속 I/O를 지원하며, 현재는 레드햇 배포판 제품군 같은 곳에서 사용되고 있다.
    • ZFS : 파일시스템과 볼륨 관리자 기능을 결합한 시스템이다.
    • FAT : 실제 리눅스용 FAT 파일 시스템 제품군으로, 그 중에서 vfat가 가장 자주 사용된다.
      • FAT을 사용하는 이동식 미디어뿐 아니라 윈도우 시스템과의 상호운용성을 목적으로 한다.
      • 볼륨에 대해 네이티브 고려사항이 그다지 적용되지 않았다.

        인메모리 파일시스템

  • 사용 가능한 인메모리 파일 시스템은 많다. 범용인 것도 있는 반면 매우 구체적인 사용 목적을 갖춘 것도 있다.
  • debugfs : 디버깅에 사용되는 특수 목적 파일시스템.
  • loopfs : 디바이스가 아닌 블록에 파일 시스템을 매핑할 수 있다.
    • 백그라운드의 메일 스레드도 참조하자
  • pipefs : 파이프에 마운트된 특수 파일 시스템. 파이프를 활성화한다.
  • sockfs : 네트워크 소켓을 파일처럼 보이게 만드는 또 다른 특수 파일 시스템. 시스템 콜과 소켓 사이에 있다.
  • swapfs : 스와핑을 실현하는 데 사용된다.
  • tmpfs : 파일 데이터를 커널 캐시에 보관하는 범용 파일 시스템. 빠르지만 데이터 유지는 되지 않는다.

쓰기 시 복사(CoW) 파일시스템

  • Copy-on-Write는 I/O 속도를 높이는 동시에 공간은 적게 사용하는 개념이다.
  • 원리
    1. 블록 A, B, C로 이루어진 원본 파일인 파일 1을 파일 2에 보사한다. 이때 실제 블록을 복사하는 대신 메타데이터(블록에 대한 포인터)만 복사 한다.
      • 메타 데이터만 생성되기 때문에 속도가 빠르며 공간도 많이 차지하지 않는다.
    2. 파일2가 수정되면 (이 상황에서는 C블록의 데이터가 변경된 것으로 가정) C블록만 복사된다. C’라는 새 블록이 생성되지만 파일2는 여전히 수정되지 않은 블록 A와 B를 가리키고 있으며, 이제 새 블록C’를 사용하여 새 데이터를 캡쳐한다.
  • 추가적으로 유니온 마운트(union mount)라는 것을 이해 해야한다.
    • 이는 여러 디렉터리를 하나의 위치로 결합해서 해당 디렉터리에 모든 참여 디렉터리가 결합된 내용(union)이 포함된 것처럼 결과 디렉터리의 사용자에게 보이게 할 수 있는 개념이다.
    • 유니온 마운트를 사용하다보면 마운트의 계층화 순서를 암시하는, 상위 파일 시스템과 하위 파일 시스템이라는 용어를 접하게 된다.
  • Unionfs : CoW 파일 시스템용 유니온 마운트를 구현한 것이다.
  • OverlayFS : 리눅스용 유니온 마운트 파일 시스템 구현이다. 파일이 열리면 모든 작업이 기본 파일 시스템에서 직접 처리된다.
  • AUFS : 도커에서 기본값으로 사용되었었다.(현재 도커는 스토리지 드라이버 overlay2와 함께 OverlayFS로 기본설정 됨)
  • btrfs b-tree 파일시스템으로, 오라클사에서 설계한 CoW이다. 많은 회사가 기여하고있으며, btrfs는 스냅샷과 자동 데이터 손상 자동 감지 같은 여러 기능이 함께 제공된다.
    • 전문적인 환경에 매우 적합하다.
This post is licensed under CC BY 4.0 by the author.

모던 리눅스 교과서 4. 접근 제어

모던 리눅스 교과서 6. 애플리케이션패키지 관리컨테이너