가상 파일 시스템
- 가상 파일 시스템(VFS : Virtual File System)의 기본 개념은 사용자로 하여금 다양한 파일 시스템을 일관된 형태로 접근할 수 있도록 하는것이다.
- 대부분의 운영체제에서는 자신의 파일 시스템만을 지원하고 있지만 ㄱ리눅스에서는 가상 파일 시스템 개념을 도입하여 여러 종류의 파일 시스템을 지원하고 있다.
- 리눅스 커널의 기본 파일 시스템은 EXt2 파일 시스템이다. 그러나 리눅스에서는 VFS를 통하여 다양한 운영체제(ex): Ms-DOS, UNIX, MINIX, Windows, NT 등)에서 사용하는 파일 시스템을 지원한다.
- VFS는 특정 파일 시스템들의 상위 계층에 위치하면서 각각의 파일 시스템을 추상화한다. 따라서 사용자 프로세스의 파일 접근을 위한 시스템 호출은 일차적으로 VFS에서 동일한 방법으로 받아들인 후 특정 파일 시스템에 해당되는 루틴을 이차적으로 호출함으로써 사용자 입장에서 마치 동일 한 파일 시스템인 것처럼 보이게 한다.
- ex) MS-DOS에서 생성된 파일 "/cdrom/test.c"를 Ext2 파일 시스템의 파일 "/tmp/test.c"로 복사할 경우 파일 시스템을 고려하지 않고 다음과 같은 명령어로 가능하다.
$ cp /cdrom/test.c/tmp/test.c
FAT 파일 시스템
MS-DOS 파일 시스템의 구조는 부트 색터(boot sector), FAT(File Allocation Table), 루트 디렉토리(root directory) 그리고 디렉토리 및 데이터 영역으로 구성되어 있다.
- 부트 섹터
- 부트 섹터는 파일 관리에 필요한 정보는 물론 시스템이 부팅될 때 MS-DOS 운영체제를 디스크로부터 메모리에 적재시켜주는 부트스트랩 루틴(bootstrap routine)을 포함하고 있기 때문에 "부트 섹터"라고 부른다. 부트 섹터에 존재하는 부트 스트랩 루틴은 ROM-BOIS에 의해 적재된 후 실행된다.
- 부트섹터의 정보는 디스켓 혹은 디스크가 포멧될 때 설정되며 항상 디스크의 첫 번째 섹터에 존재한다.
- 부트 섹터 다음에는 MS-DOS에서 예약해 놓은 섹터들이 존재한다.
- ex) 부트스트랩 루틴을 하나의 섹터에 저장할 수 없을 경우 DOS에서 예약해놓은 섹터들을 연결하여 사용한다. 이에 대한 경우 DOS에서 예약해 놓은 섹터들을 연결하여 사용한다. 이에 대한 정보는 부트 섹터의 오프셋 0Eh에 기록되어 있으며 만약 부트 섹터가 하나의 섹터에 모두 저장될 수 있는 경우에는 부트 섹터의 오프셋0Eh에 1이 기록되고 두 번째 섹터로부터 FAT(File Allocation Table) 섹터가 존재하게 된다.
- FAT
- MS-DOS에서 새로운 파일을 생성하거나 기존의 파일을 확장하기 위한 디스크 공간 관리는 FAT(File Allocation Table)을 이용하여 이루어진다. FAT 섹터는 MS-DOS에서 예약해 놓은 섹터 바로 다음에 위치하는데 디스크에 존재하는 FAT의 수는 부트 섹터의 오프셋 10h에 기록되어 있다.
- MS-DOS에 디스크 공간을 효율적으로 관리하기 위해 몇개의 연속된 섹터들을 하나의 클러스터(cluster)로 정의하여 디스크를 사용하는 최소 단위로 사용한다. 이에 대한 정보는 부트 섹터의 오프셋 0Dh에 기록되어 있다.
- FAT의 엔트리는 클러스터(cluster)와 1:1 관계를 가지고 있으며 각 엔트리의 내용과 의미는 다음과 같다.
내용 | 의미 |
000h FFF0h - FFF6h FFF7h FFF8h - FFFh xxxxh |
사용되고 있지 않은 클러스터 MS-DOS에 의해 예약된 클러스터 고장난 클러스터 파일에 할당된 마지막 클러스터 파일에 할당된 다음 번째 클러스터 번호 |
FAT 엔트리 내용과 의미
- 루트 디렉토리
- 루트 디렉토리는 FAT 바로 다음 섹터에 위치하는데 루트 디렉토리에 존재하는 엔트리의 수는 부트 섹터의 오프셋 11h에 기록되어 있다. 디렉토리 엔트리의 크기는 32바이트이며 그 내용은 아래와 같다.
오프셋 | 정보 | 길이 |
00h | 파일 이름 | 8바이트 |
08h | 확장자 이름 | 3바이트 |
0Bh | 파일 속성(attribute) | 1바이트 |
0Ch | 사용되지 않음 | 10바이트 |
16h | 변경된 시간 | 2바이트 |
18h | 변경된 날짜 | 2바이트 |
1Ah | 파일이 저장된 첫 번째 클러스터 번호 | 2바이트 |
1Ch | 파일 크기 | 4바이트 |
디렉토리 엔트리의 구조
- 디렉토리 엔트리의 처음 8바이트에 파일명이 기록되기 때문에 MS-DOS에서 파일명은 8자까지 유효하다. 만약 파일명이 8바이트 보다 작을 경우에는 파일명이 왼쪽에 기록되고 나머지 부분은 공백 문자로 채워진다. 또한 파일명과 확장자 사이의 점('.')은 저장되지 않는다.
- 파일에 대한 속성은 1바이트로 표시되는데 각 비트의 의미는 아래와 같고 하나의 파일에 대한 속성은 각 비트들의 조합으로 나타난다.
비트 | 의미 |
0 | 1 = 읽기 전용(read only) |
0 = 읽기/쓰기(read/write) | |
1 | 1 = 파일명 숨기기(hidden file) |
2 | 1 = 시스템 파일(system file) |
3 | 1 = 볼륨 이름(volum name) |
4 | 1 = 디렉토리(directory) |
5 | 아카이브 비트(Archive bit) |
6-7 | 사용하지 않음 |
속성 바이트의 구조
- 데이터 영역
- 데이터 영역은 루트 디렉토리 바로 다음 섹터부터 나머지 섹터에 해당되며 사용자의 프로그램 혹은 데이터와 서브 디렉토리를 저장하는데 사용된다.
- ex) MS-DOS의 파일 시스템에 "/MSDOS.SYS" 파일이 클러스터 번호 2번부터 저장되어 있다고 가정할 경우 FAT와 루트 디렉토리의 관계는 아래의 이미지와 같다.
- 위의 상황에서 "/MSDOS.SYS" 파일을 접근하는 과정은 다음과 같다.
- 루트 디렉토리를 검색하여 파일명을 확인한다
- 파일명에 해당한 첫 번째 클러스터 번호(02)를 찾는다.
- FAT 엔트리(02)로부터 다음 클러스터의 번호(03)를 찾는다.
- 동일한 방법으로 마지막 클러스터 번호(1E)까지 찾아간다.
- 새로운 파일 을 생성할 경우에 FAT를 검색하여 빈 클러스터를 할당하고 다음 클러스터 번호를 연결한다. 또한 기존의 파일을 삭제할 경우에는 디렉토리 엔트리의 파일명의 첫 번째 바이트를 단순히 "E5h"로 변경한다. 이러한 정보를 이용하면 삭제된 파일의 복구가 가능하다.
Ext2 파일 시스템
- UFS(Unix File System)를 기본으로 개발된 Ex2(Second Extended)파일 시스템은 리눅스의 기본 파일 시스템이지만 현재에는 저널링(Journaling) 기능이 추가된 Ext3, Ext4 파일 시스템들이 많이 사용되고 있다.
- EXT2 파일 시스템의 구조는 부트 블록과 여러 개의 블록 그룹(block group)으로 구성되어 있다.각각의 블록 그룹은 슈퍼 블록, 블록 디스크립터, 블록 비트맵, I-노드 비트맵, I-노드 블록, 그리고 디렉토리 및 데이터 블록으로 구성된다.
- 부트 블록[N Blocks]
- 부트 블록은 디스크의 첫 번째 블록에 위치하며 시스템이 부팅될 때 리눅스 커널을 디스크로부터 메모리에 적재시켜 주는 부트 스트랩 루틴(bootstrap routine)을 포함하고 있기 때문에 "부트 블록"이라고 부른다.
- 슈퍼 블록[1 Block]
- 슈퍼 블록(super block)은 디스크의 두 번째 블록에 위치하며 디스크의 빈 공간 관리와 할당 정책에 관련된 중요한 정보를 가지고 있다
- 총 I-노드 수 및 사용 가능한 I-노드 수
- 총 블록 수 및 사용 가능한 블록 리스트
- 블록 크기(1KB, 2KB, 4KB)
- 그룹당 I-노드 및 블록 수
- 피일 시스템 상태
- 생성한 운영체제
- 파일 시스템이 마지막으로 갱신된 날짜 및 시간
- 이러한 정보들이 초기 값은 파일 시스템을 만들 때 시스템 관리자에 의해 설정되며 파일 생성 및 삭제 과정에서 파일 시스템에 의하여 갱신된다.
- 새로운 파일을 생성할 경우 사용 가능한 디스크 블록을 빠르게 검색하기 위하여 슈퍼 블록의 내용은 부팅 시 메모리에 복사하여 유지한다. 또한 메모리에 존재하는 슈퍼 블록의 내용이 변경되면 그 내용과 갱신된 날짜 및 시간을 주기적으로 디스크에 복사하여 디스크의 내용과 일치하도록 한다.
- 슈퍼 블록(super block)은 디스크의 두 번째 블록에 위치하며 디스크의 빈 공간 관리와 할당 정책에 관련된 중요한 정보를 가지고 있다
- 그룹 디스크립터 블록[N Blocks]
- 블록 그룹 디스크립터(descriptor)는 각 블록 그룹을 관리하는 정보로써 다음과 같은 내용을 가지고 있다.
- 블록 비트 맵 블록 번호
- I-노드 비트 맵 블록 번호
- I-노드 테이블 블록 번호
- 빈 블록 수
- 빈 I-노드 수
- 디렉토리 수
- 블록 그룹 디스크립터(descriptor)는 각 블록 그룹을 관리하는 정보로써 다음과 같은 내용을 가지고 있다.
- 블록 혹은 I-노드 비트 맵 블록[1Block]
- 블록 혹은 I-.노드 비트 맵은 데이터 혹은 I-노드를 할당할 때 빈 공간을 찾기 위하여 블록 혹은 I-노드가 할당된 상태를 비트 단위로 표시한다. 즉, 비트 값이 0이면 블록 혹은 I-노드가 할당되지 않았음을 의미하고 1이면 블록 혹은 I-노드가 할당되어 사용되고 있음을 의미한다. 블록 혹은 I-노드 비트 맵은 각각 한 개의 블록을 사용하기 때문에 블록 크기에 따라 표시할 수 있는 블록 혹은 I-노드의 개수가 결정된다.
- I-노드 블록[N Blocks]
- 리눅스에서는 각 파일에 대한 정보를 저장하기 위하여 I-노드(index Node)라 일컫는 자료구조를 사용한다. 파일 시스템에 존재하는 각 파일은 하나의 I-노드를 갖고 있으며 I-노드마다 고유의 번호가 할당된다. I-노드 번호는 1부터 시작되며 루트 디렉토리 파일의 I-노드 번호는 2번으로 예약되어 있다. I-노드 블록은 여러 개의 블록으로 구성되고 다음과 같은 내용을 가지고 있다.
- 파일의 종류(일반파일, 디렉토리 파일, 장치 파일 등)
- 파일의 링크 수
- 파일 소유자(uid, gid)
- 파일의 크기
- 파일이 저장된 블록 주소([15] * 4B)
- 접근 모드 및 시간
- 파일에 대한 모든 정보를 가지고 있는 I-노드는 디스킁테 존재하기 때문에 보통 "디스크 I-노드"라고도 부른다. I-노드의 크기는 128B로 동일하며 여러 개의 I-노드들이 선형 배열(linear array)로 저장되어 있다. 따라서 블록 크기가 1KB일 경우 블록당 8개의 파일을 접근하기 위해서는 그 파일에 해당하는 정보를 빠르게 검색해야 하기 때문에 디스크 I-노드의 내용을 메모리에 복사하여 사용한다. 이것을 "디스크 I-노드"와 구별하여 "메모리에 존재하는 I-shem"라고 부른다. 결국 I-노드의 내용은 디스크와 커널 내부의 내용을 디스크에 갱신시킬 필요가 있다.
- I-노드의 중요한 정보 중 하나는 해당 파일의 데이터가 존재하는 디스크 블록 주소이다. 디스크 블록 주소를 지정하기 위한 엔트리 수는 15개이다.
- 리눅스에서는 각 파일에 대한 정보를 저장하기 위하여 I-노드(index Node)라 일컫는 자료구조를 사용한다. 파일 시스템에 존재하는 각 파일은 하나의 I-노드를 갖고 있으며 I-노드마다 고유의 번호가 할당된다. I-노드 번호는 1부터 시작되며 루트 디렉토리 파일의 I-노드 번호는 2번으로 예약되어 있다. I-노드 블록은 여러 개의 블록으로 구성되고 다음과 같은 내용을 가지고 있다.
처음 12개의 엔트리는 직접적으로 데이터 블록을 가리키며 나머지 13, 14, 15 번째 엔트리는 간점(indirect), 이중 간점(double indirect), 삼중간접(triple indirect)으로 데이터 블록을 가리킨다. 따라서 삼중 간접에 의해 저장된 데이터를 접근하기 위해서는 실제 데이터 블록의 주소를 검색하기 위하여 세 번의 디스크 블록을 검색해야하는 오버헤드가 있다. 그러나 이러한 디스크 블록 할당 정책은 I-노드의 크기를 작게 유지하면서 매우 큰 크기의 파일을 지원할 수 있는 장점이 있다.
ex) 블록 크기가 1KB이고 블록 주소를 4B로 표현할 경우 블록 당 256개의 블록 주소를 지정할 수 있다.
이 경우 (12+256+256*256 *256)*1KB ≒ 16KB 크기의 파일 지원이 가능하다.
- 디렉토리/데이터 블록[N Blocks]
- I-노드 블록의 다음 블록에서부터 나머지 블록들은 일반 파일의 데이터 혹은 디렉토리 파일의 내용이 저장된다. 저장된 내용이 보통 파일인지 디렉토리 파일인지에 대한 구별은 이 블록을 지정하고 있는 I-노드에 기록되어 있는 파일 종류에 의해 이루어진다.
- 루트 디렉토리 블록의 구조는 I-노드 번호와 레코드 및 파일명의 길이, 그리고 파일명으로 구성되며 사용자에 의해 주어진 파일명을 I-노드 번호로 변환하는데 이용한다.
변위 | I-노드 번호 (4바이트) |
레코드 길이 (2바이트) |
파일명 길이 (2바이트) |
파일명 (최대 255바이트) |
0 | 2 | 12 | 1 | . |
12 | 2 | 12 | 2 | .. |
24 | 12 | 12 | 3 | etc |
36 | 13 | 12 | 3 | bin |
48 | 14 | 12 | 3 | dev |
루트(/) 디렉토리 구조
"."와 ".."은 현재 디렉토리와 부모 디렉토리를 각각 의미하며 I-노드 번호가 모두 2이므로 루트 디렉토리임을 알 수 있다.
따라서 루트 디렉토리 파일에 관한 정보는 2번 I-노드에 기록되어 있다.
ex) "/etc/passwd" 파일명에 해당되는 블록 번호를 찾아가는 과정은 다음과 같다.
- 2번 I-노드로부터 "/" 디렉토리 파일이 저장된 블록 주소(ex: 200)를 얻는다.
- 루트 디렉토리 블록에서 "etc" 파일명에 해당한 I-노드 번호(ex:12)를 얻는다.
- 12번 I-노드로부터 "etc" 디렉토리 파일이 저장된 블록 주소(ex:215)를 얻는다.
- 20번 I-노드로부터 "passwd"파일이 저장된 블록 주소에(ex:250)를 얻는다.
- 이러한 과정에서 I-노드에 대한 검색이 여러번 요구된다. 또한 참조하려는 파일의 I-노드에 대한 정보는 참조가 끝날 때까지 계속적으로 요구될 것이다. 따라서 어떤 파일을 참조할 때마다 그 파일에 대한 정보를 얻기 위하여 디스크를 접근하는데 오버헤드가 발생한다.
- 이러한 오버헤드를 개선하기 위하여 파일을 참조하기 전에 반드시 파일 열기(open)를 하도록 한다.
- 파일 열기를 처리하는 과정에서 디스크에 존재하는 해당 파일의 I-노드 정보는 커널 내부의 메모리에 복사된다. 이것을 "메모리에 존재하는 I-노드(in-core-i-node)"라고 부른다.
- 따라서 한 번 열기가 수행된 파일에 대한 I-노드 정보는 디스크가 아닌 메모리에 존재하는 I-노드로부터 빠르게 검색할 수 있다.
Reference
개념 이해를 위한 운영체제
VFS 1 - 가상 파일시스템(Virtual File System)
사용자 태스크들은 open(), read(), write(), close() 등의 시스템 콜을 사용해 파일시스템에 접근한다. 반대로 파일시스템은 함수를 구현하여 상위계층에 제공해야하는 데 이는 구현하기 나름이다. 파
velog.io
'CS > 운영체제' 카테고리의 다른 글
[Chapter 6] 개념 이해를 위한 운영체제 [파일 시스템 - 디스크 관리] (0) | 2025.03.03 |
---|---|
[Chapter 6] 개념 이해를 위한 운영체제 [파일 시스템 - 빈 공간 관리] (0) | 2025.03.03 |
[Chapter 6] 개념 이해를 위한 운영체제 [파일 시스템 - 개요] (0) | 2025.03.02 |
[Chapter 5] 개념 이해를 위한 운영체제 [메모리 관리 - 다중 프로그래밍 시스템] (0) | 2025.02.27 |
[Chapter 5] 개념 이해를 위한 운영체제 [메모리 관리 - 단일 프로그래밍 시스템] (0) | 2025.02.27 |