Search
💾

[OS] File Systems Implementation 1

contents

들어가며

Storage Data에 접근하는 방법에서는 순차 접근, 직접(임의) 접근이 가능한 경우가 존재합니다.
순차 접근 - 테이프 같은 매체
하나를 보고나서 중간을 건너뛰고 싶다면 테이프를 감아야 합니다.
직접 접근 - 하드 디스크, 플래시 메모리, CD
어떤 내용을 보다가 건너뛸 내용이 있으면 건너뛰기 가능합니다.
하지만 직접 접근 가능한 매체라 하더라도 데이터를 어떻게 관리하느냐에 따라서 순차접근만 허용되는 경우가 있고, 직접 접근이 가능한 경우가 있습니다.
 : 왜 그럴까요?

Allocation of File Data in Disk

파일은 균일하지 않은 여러가지 다른 크기를 각각 가지고 있습니다. 하지만 디스크에다가 파일을 저장할 때는 동일한 크기의 섹터 단위로 나누어서 저장합니다.
파일 시스템, 디스크 외부에서는 디스크 각각의 동일한 크기의 저장 단위를 논리적 블록이라고 부름
실제로 디스크 내부에서는 각각의 섹터 단위로 데이터를 저장
  어떤 임의의 크기의 파일을 동일한 크기로 나누어서 저장을 하기 때문에 페이징 기법하고 유사하다고 볼 수 있다.
디스크에 파일의 내용을 저장하는 방법에는 3가지가 있습니다.
1.
Contiguous Allocation(연속 할당)
2.
Linked Allocation : 링크를 둔 연결 할당
3.
Indexed Allocation : 인덱스를 두는 방식

Contiguous Allocation

하나의 파일이 디스크 상에 연속으로 저장되는 방법
Contiguous Example
count 파일은 Start 위치가 0이고, length는 2이다. 블록 2개로 구성되는 파일이기때문에 (0, 1) 블록으로 인접한 블록 번호를 가진다.
mail 파일은 length 6으로 구성되는 파일이다. Start 위치가 19이기 때문에 (19, …, 24) 블록으로 연속해서 들어간다.
list 파일은 28번부터 31번까지 4블록에 걸쳐서 저장된다.
장점
1.
빠른 I/O가 가능합니다.
하드 디스크같은 매체는 대부분의 접근 시간이 디스크 헤드가 바깥 트랙에서 안쪽 트랙으로 움직이는 시간입니다. 실제로 데이터를 읽거나 쓰는 크기는 시간에 큰 영향을 미치지 않습니다.
디스크의 헤드가 한 번에 많은 양의 데이터를 한꺼번에 받아올 수 있기 때문에 어떤 파일을 통째로 읽고 싶을 때 사용하기 좋습니다. 같은 트랙 위에 6개의 블록을 다 가져와서 두게 되면 또 가져오지 않아도 됩니다.
한 번의 싱크로 많은 양을 가지고 올 수 있어서 빠른 I/O가 가능합니다.
2.
프로세스의 swap area
프로세스의 주소 공간 중 일부를 물리적인 메모리에서 쫓아내고 필요할 때 올려두는 용도로 사용합니다.
파일 시스템은 연속적인 공간이고 전원이 나가도 유지가 되어야 하지만 Swap area는 의미없는 정보로 임시 저장하는 용도로 사용됩니다.
대용량의 데이터를 디스크에 올렸다가 빨리 메모리로 올리고 해야하기 때문에 공간 효율성보다는 속도 효율성이 더 중요합니다. 디스크를 많이 차지하더라도 지워질 것이기 때문입니다.
3.
실시간 file용으로 연속 할당을 사용하면 속도가 빨라서 좋습니다.
4.
직접 접근이 가능합니다.
상단의 예시에서 mail의 길이가 6인데, 해당 파일에서 앞에서부터 5번째 블럭을 보고 싶다면 4개의 블록을 다 접근하지 않더라도 볼 수 있습니다.
연속으로 저장되어 있기 때문에 중간에 있는 블록의 위치도 알 수 있습니다.
단점
1.
외부 조각이 생길 수 있습니다.
파일의 길이가 균일하지 않아서 free블럭(내용이 들어있지 않은 블럭)이 생성됩니다.
만약 새로운 파일이 생성되는데 그 파일의 크기가 3이라고 한다면 상단의 예시에서 17-18 블록 사이에는 못 들어가게 됩니다. 비어있지만 외부 조각때문에 활용이 불가능합니다.
2.
파일의 크기가 중간 중간 변경될 수 있습니다.
파일의 크기가 커질 수 있는데 한계가 생깁니다.
위의 예시에서 14-16 블록의 경우, 4-5개까지 크기를 키우는 건 가능한데, 6개로 수정하고 싶다면 불가능합니다. 연속 할당 규칙하에 뒤에 2개까지만 가능하게 됩니다.
파일이 커질 걸 대비해서 빈 공간을 확보한다고 해도 거기까지만 가능하고 그 이상은 불가능합니다.
만약 빈 공간으로만 남겨두지 않고 미리 할당을 해둔다면 당장 사용되지 않는 공간으로 남기 때문에 내부 조각이 발생합니다. 즉, 공간의 낭비가 발생합니다.
3.
연속 할당은 파일의 크기가 균일하지 않기 때문에 중간 중간에 홀이 생깁니다.

Linked Allocation

파일의 데이터를 연속적으로 배치하지 않고 빈 위치면 다 들어갈 수 있게 합니다.
Linked Example
Jeep이라는 파일이 있다.
시작 위치는 9번 블록
9번에 가면 파일의 데이터가 16번에 있다고 적혀있음
16번에 갔더니 1번에 있다고 적혀있음
1번에 갔더니 10번에 있다고 적혀있음
10번에 갔더니 25번에 있다고 적혀있음
25번에는 더이상 내용이 없고 끝이 났다는 표시를 -1로 해둠
  시작 위치만 가지고 있고 그 다음 위치는 파일에 가보면 존재합니다. 만약 뒤에 내용이 더 있다면 해당 위치를 기록해둡니다.
장점
1.
외부 조각이 발생하지 않습니다.
비어있는 블록이면 어디든지 아무 내용이나 들어갈 수 있습니다.
단점
1.
직접 접근이 불가능 합니다.
위의 예시에서 시작 위치로부터 4번째 데이터를 찾는다고하면 시작 위치부터 차근차근 4번째 위치를 찾아가야 합니다. linked allocation은 중간 위치를 보려면 앞 위치를 다 탐색해야 확인이 가능합니다.
순차 접근만 가능합니다.
블록 위치가 여러 곳에 있기 때문에(연속X) 디스크 헤드가 싱크하면서 움직여서 다음 내용을 봐야 합니다. 만약 다음 위치가 멀리 떨어져 있다면 순차 접근에 의한 시간이 많이 들게 됩니다.
2.
Reliability 문제가 발생합니다.
디스크의 섹터들에서 베드 섹터가 날 수 있습니다.
파일을 구성하는 섹터의 갯수가 1000개가 된다면 중간에 하나가 베드 섹터가 나면 다음 것들이 모조리 접근 불가능하게 됩니다. 포인터가 상당히 많이 유실되어서 뒷 부분을 완전히 다 놓치게 되는 겁니다.
3.
포인터로 인해서 저장공간 비효율 문제 발생
보통 디스크에서는 하나의 섹터를 512바이트로 구성하기 때문에 디스크 바깥쪽에서 디스크에 접근할 때 512 바이트의 배수로 구성을 합니다.
이 때 포인터를 위해서 4 바이트가 더 요구되는데, 결론적으로 데이터가 저장될 수 있는 공간은 (512 - 4) 바이트가 됩니다.
이 때문에 512 바이트를 저장하려고 할 때 2섹터에 나눠서 저장되는 문제가 발생합니다. 상당히 비효율적입니다.
  이걸 이대로 사용하지 않고 변형해서 효율적으로 사용할 수 있는데 이게 Fat File System

Indexed Allocation

디렉토리가 가진 게 인덱스 블럭이기 때문에 어디에 저장이 되어 있다는 위치 정보를 하나의 블럭에다가 열거해두는 방식
Indexed Example
직접 접근이 가능하게 하기 위해서는 인덱스를 가르키게 해둡니다.
jeep 은 5개의 블록으로 구성이 됩니다.
첫번째 인덱스는 9
다섯 번째 인덱스는 25
인덱스 블록에다가 내용으로 적어둠
만약 4번째 인덱스를 보고 싶다면 인덱스 블록만 살펴보고 찾아가면 됨
  건너뛰어서 직접 접근이 가능하다.
장점
1.
직접 접근 가능
2.
순차 접근에서 홀이 생기는 문제를 해결할 수 있습니다.
비어있는 위치라면 어디든 가능합니다.
단점
1.
아무리 작은 파일이라고 해도 블록이 2개는 필요합니다.
인덱스, 실제 데이터 저장하기 위한 블록이 필요하기 때문에 파일이 굉장히 작은 경우에 공간 낭비가 발생합니다.
파일의 분포를 보면 실제로 많은 파일들이 작습니다.
2.
굉장히 큰 파일의 경우에는 하나의 인덱스 블록으로 다 표현을 못합니다.
블록 하나가 512바이트라고 하면 들어갈 수 있는 갯수가 한정적입니다.
큰 파일은 인덱스 블록 하나로 표시를 할 수 없기 때문에 다른 방법을 사용해서 해결해야 합니다.
linked scheme
: 인덱스 블록에 실제 이 파일의 위치가 어딘지 적다가 크기를 커버하지 못하면 마지막 부분에 또다른 인덱스 블록을 가르키게 합니다.
마지막 위치는 파일의 내용이 아니라 또다른 인덱스입니다.
해당 인덱스에는 파일의 위치 정보가 적혀있습니다.
multi-level index
: 하나의 인덱스 블록이 직접 파일 위치를 가르키게 하는게 아니라 이게 또 다른 인덱스를 가르키게 합니다.
2단계 페이지 테이블 쓰듯이 두 번을 거쳐야만 파일의 위치를 가르키게 됩니다.
굉장히 큰 파일을 표현할 수 있지만, 인덱스를 위한 공간 낭비가 있다는 게 단점입니다.
위의 3가지 방법은 이론적으로 이런 할당이 가능하다고 설명을 한 것 입니다. 실제로는 어떤 방식을 사용할까요?

UNIX 파일시스템의 구조

가장 기본적인 파일 시스템 구조로 여기서 발전되어서 fast, 등등으로 변형되었습니다.
하나의 논리적인 디스크(파티션) 존재하고 여기다가 파일 시스템(UNIX 파일시스템)을 설치해둡니다.
UNIX는 저장되는 구조가 크게 4가지로, Boot block, Super block, Inode list, Data block입니다.
Boot block
부팅에 필요한 정보
유닉스만 그런게 아니라 어떤 파일 시스템이건 Boot block이 제일 먼저 나옵니다.
example) 컴퓨터에 어떤 파일 시스템이 깔려 있는지 모르는데 컴퓨터를 켜서 부팅을 해야하는 상황, 어디있는 데이터를 메모리로 올려서 부팅을 할 수 있는가?
boot block을 올려서 그 안에 있는 bootstrap loader를 사용합니다. 시키는대로 하면 운영체제 커널의 위치를 찾아서 정상적으로 부팅이 진행되도록 합니다.
Super block
파일 시스템에 관한 총체적 정보를 담습니다.
어디가 빈 블럭이고 어디가 실제로 파일이 저장된 블록인지 관리합니다.
Inode list에 관한 정보나 어디까지가 list가 있고 어디부터 데이터 블록이 있고를 총체적으로 관리합니다.
  : 파일의 메타데이터는 그 파일의 가지고 있는 디렉토리에 기록되어 있다고 배웠지만 실제 파일 시스템의 구현에서는 디렉토리가 다 가지고 있는게 아닙니다.
UNIX의 경우에는 디렉토리는 지극히 일부만 가지고 파일의 메타데이터를 다른 곳에 저장하고 있는데 그게 Inode list라는 부분입니다.
Index node
파일의 메타데이터를 가지고 있는 구조. 메타 데이터는 파일의 소유주, 접근 권한, 수정 시간, 위치정보를 가집니다.
파일 하나당 inode가 하나씩 할당됩니다.
UNIX는 file의 이름은 디렉토리에서 메타데이터로 가지고 있습니다.
빨간 색처럼 하나씩 정장될 수 있는 위치가 있고 빨간색으로 표시된 inode 하나가 바로 파일 하나당 iunode가 하나씩 할당. 요 inode는 . 위치 정보를 집중해서 설명해보겠다. 유닉스는 모두 메타데이터를 inode가 가진 건 아니고 file의 이름은 디렉토리가 가지고 있다. 즉, 디렉토리에 가면 메타데이터 중 이름은 직접 가지고 나머지는 inode에 저장되어 있어서 inode번호를 가지고 있다. 그래서 inode 10이라고 하면 나머지는 inodelist에서 10번 inode에 메타데이터가 있을 것. 유닉스 파일 시스템의 핵심, 기본적 구조
파일의 위치 정보는 어떻게 저장? 유닉스 파일 시스템 기본적으로 index 할당을 변형해서 사용중이다. inode라는건 크기가 고정되어 있음. 가변적인게 아니고 미리 할당된 크기가 딱딱 구성됨. 위치 정보를 나타내는 포인터 갯수도 유한한 것. 그치만 inode를 가지고 굉장한 큰 파일을 나타낼 수 있어야 한다. 유닉스에서는 index 할당 중에서 (밑에 있는 사진)으로 위치 정보를 구성. 굉장히 작은 데이터는 direct index pointer만을 사용해서 그 파일의 위치를 충분히 가르킬 수 있다. 굉장히 큰 파일의 경우에는 indirect를 이용. single indirect는 따라가면 index 블록이 있고 그 인덱스 블록에는 포인터가 여러개(실제 파일 내용 가르키는 포인터) 존재. 더 큰 파일을 표현하려면 밑에 있는 포인터 하나가 그 용도로 쓰임. 2번해야지 실제 파일 위치가 저장. 이걸로 부족하면 triple 사용. 3단계 인덱스 구조를 통과해야지 실제 파일의 위치 정보 존재.
왜 효율적인가? 대부분의 파일은 크기가 작습니다. 작은 파일들은 한번의 포인터 접근으로 inode만 올려두면 위치를 바로 알 수 잇고, 큰 파일은 indirect 블록을 이용해서 인덱스를 추가적으로 접근해서 파일의 위치를 찾을 수 있음. 실제로 계산해보ㄴ면 굉장히 큰 파일을 한정된 크기의 inode로 지원할 수 있다는 걸 알 수 있다.
요약을 하자면 유닉스는 4가지로 디스크를 관리하고 있고 메타 데이터는 inodw에다가 별도로 관리한다.
마이크로 소프트 사가 MS Dos를 만들었을 때 처음 만든 파일 시스템. 최근 윈도우즈 계열은 이걸 일부 사용.
구조가 부트 블럭, FAt, Root 디렉토리, Data bloack
부트 블럭은 어디나 동일
FAT: 파일의 메타 데이터 일부를 FAT이라는 곳에 저장. 위치 정보만 따로 빼둠. 나머지는 디렉토리가 가짐. 첫번째 위치가 어딘지도 디렉토리가 가짐.
1.
Data block에 가면 첫번째 위치가 있음.
2.
217에 가면 그 파일의 첫번째 내용이 있음.
3.
링크드는 첫번째 블록이 크다면 끝에 두번째 블록의 인덱스를 저장하는데 문제가 뭐냐면 중간에 베드 섹터가 나면 문제, 약간의 크기가 줄어듦으로 512를 다 사용할 수 없다는 문제.
4.
FAT은 217블록의 다음 블록이 뭔지를 각 블록이 담는 게 아니고 FAT이라는 별도 테이블에 담음. 배열의 크기는 디스크가 관리하는 데이터 블록의 갯수만큼 가진다. 숫자를 하나 담을 수 있는데 그 블록의 다음 블록이 어딘지를 담음. 무슨 의미인지는 모르겠지만 그 블록의 다음 블록의 번호를 저장, 이 파일의 경우에는 217 → 두번째는 FAT를 보고 217 엔트리에 가면 618로 써있음 → 618로 이동 → 3번째는 FAT의 618 엔트리에 가봄 → 339 → 339에 가봤더니 EOF(끝났다는 뜻) 이파일은 339에서 끝나고 더이상의 내용이 없구나.
5.
링크드 할당을 변형 → 실제 블록을 접근하는게 아니라 FAT만 확인하면 다음 위치 확인 가능
직접 접근 가능
링크드는 순차 접근만 가능했음. 여기서는 직접 접근 가능. FAT이라는 건 작은 테이블, 이미 메모리에 올라가 있음. 4번째 블록을 보겟다고 하면 테이블을 메모리에 오려두고 쭉 따라가는 것이기 때문에 곧바로 5번째 위치 파악가능. 실제 데이터 블록을 봐야지만 볼 수 있는게 아니고 바로 볼 수 있음. 링크드 할당의 단점을 모조리 극복. Realility 문제 해결.
좀 더 구체적으로 어떤 식으로 해결하냐면 포인터 하나가 유실되더라도(베드 섹터) 펫에 내용이 있어서 데이터 블록의 내용과 펫이 분리. 펫은 대단히 중요한 정보. 따라서 한 카피만 두는 게 아니고 디스크에 두 카피 이상을 저장. Reability 개선.
512바이트 충분히 활용 가능. 링크드 할당을 변형했지만 단점 모두 극복 완료.
실재로는 파일 시스템이 대단히 많다. 기본적인 방법을 상당히 개선해서 사용 중. → iOS 살펴보기

Free space management

앞에서 논리적 디스크의 정보들 중에서 파일의 할당된 데이터를 어떻게 관리하는가만 말하고 비어있는 곳은 어떻게 관리하는지 말 안해줬음. 그래서 설명해주겠다.
비어있는 블록 어떻게 관리하는가.?
몇가지가 있음
1.
bit map
각각의 블록 별로 번호가 있음. 그걸 유닉스 같으면 super block에다가 bit를 둬서 첫번째 블록이 사용중인지 비어잇는지 0과 1로 표시. 예를 들어서 비트맵의 크기는 여기있는 블록의 갯수만큼으로 비트맵으로 구성. 비트맵이 표시하는 바는 그 값이 0이다. 비어있음. 1이라면 이미 파일에 할당된 블록. 파일 시스템이 파일 새로 만들어지거나 파일 크기가 커지면 비어있는 블록중에 하나에 할당. 삭제되거나 그러면 1을 0으로 바꾸어줌. 파일 시스템이 관리. 비트맵이라는건 디스크에 부가적 공간을 필요로 함(특징., 단점) 그렇게 많은 공간은 아닐것. 블록 하나당 1비트.
장점? 연속적인 빈 블록을 찾는데 좋다. 가능하면 연속할당을 쓰지 않지만 연속적인 빈 공간에 할당해주면 좋다. 디스크 헤드가 움직이지 않아도 되니깐. 한꺼번에 읽어올 수 있어서. 비트맵을 스캔하면서 연속적인 곳 찾기에 좋다. 작업에 효과적
2.
linked list
비어있는 블록들을 연결해둠. 비어있는 거라서 포인터를 가지고 다음 위치가 어딘지 저장 가능. 비어있는 블록의 첫 위치만 포인터로 가지고 있고 그 다음 위치는 실제 그 빈 블록에 가면 다음번 빈 블록 위치를 포인트 하는게 이 방법. 비트맵에 비해서 추가적 공간 낭비 없음. 하지만 연속적인 빈공간을 찾기가 힘듦. 헤드가 시크를 해서 어딘지 어딘지 다 따라가서 연속적인 곳을 찾는건 비효율적(이론적)
실제로 쓰기가 힘들다. 연속적 가용공간 찾기가 어렵기에.
3.
grouping
index 할당같은 프리 블록을 관리하는데 사용
linked list 방식 변형
처음 빈 위치에는 인덱스 역할을 해서 첫번째 빈 위치에 가면 비어있는 블럭들의 포인터들이 쭉 저장이 되어 있고 비어있는걸 가르킴. 더 있다면 마지막에 인덱스를 저장,
인덱스 형식으로 그룹핑을 해서 빈 브록의 위치를 가르킴.
비어있는 블록을 한꺼번에 찾기에는 ㅣinked list보다 효유ㅜㄱ적이지만 연속적인걸 찾기에는 효과적이지 않음.
4.
counting
연속적인 빈 블록을 표시하기 위해서
빈 블록의 첫 위치와 거기 부터 몇개가 빈 블록인지 쌍으로 관리. 빈 블록을 가르키기만 하는게 아니라 빈블록의 위치를 가르키고 거기서 부터 몇개가 비어있다. 이런식으로 관리. 연속적으로 5개 빈 블록 찾고 싶다면free block의 갯수를 가르키는 필드가 5이상인걸 찾으면 된다.
디렉토리릉 어떻게 구현하는지?
디렉토리는 파일의 메타 데이터를 관리하는 특별한 파일. 디렉토리의 파일 내용을 어떻게 저장할 것인가?
1.
Linear list
단순히 디렉토리 파일을 파일의 이름하고 다른 메타 데이터들을 쭉 순차적으로 저장. 요 메타데이터는 크기가 가변적이지 않고 고정적. 이름ㅇ,ㄴ 몇바이트, 나머지 메타데이턴 9비트, 사이즈는 몇바이트 이ㅓㄹㅎ게 큭ㅡ기 고정해서 관리. 디렉토리에 대한 연산이 주어져 잇다면 그 디렉토리 밑에 어떤 파일이 있는지 찾으라고 하면 이름의 필드가 어떤 단위로 구성되는지 알아서 이름을 어떤 것가 있는지 찾기 쉬움. 순차적으로.
linear lsit형태로 저장. 구현은 간단하지만 어떤 연산에 대해서 시간이 많이 필요. 특정 파일이 있ㄴㄴ지 다 검색해야해서 비효율적
2.
Hash Table
파일의 이름을 그냥 저장하는게 아니라 해쉬 하수를 적용. 어떤 인풋값이 주어지더라도 해시 함수를 적용하면 해시 함수 결과값이 특정 레인지로 한정된다. 해시 함수를 10으로 나누는 나머지 연산을 쓰겟따고 하면 0~9사이의 값만 나오는 거 같이 특정 범위 안으로 값이 나옴. 파일의 이름도 적용가능. 해시 함수 f를 적용헤ㅐㅆ을 대 그 파일의 이름에 대한 해시 결과값이 1~n사이로 나오도록. 파일의 해시함수 결과값에 해당하는 엔트리에다가 그 파일의 결과값을 저장.
파일 이름 ccc에 대해 해시함수를 적용했더니 3 나옴. 그러면 3 엔트리에다가 그 파일의 이름, 그 파일의 메타데이터 저장. 이런식으로 하면 어떤 파일이 이 디렉토리 아래 있다 찾아라(잇는지 없는지) 라고 한다면 순차적으로 탐색하는게 아니라 해시 함수를 적용하고 결과값에 해당하는 엔트리만 찾아보면 된다.
만약, 디렉토리 밑에 있다면 그 엔트리에 있어야 함. 없다면 없는 거니깐 효율적으로 사용 가능.
물론 해시를 사용하면 colision이 발생할 수 있음. 서로 다른 파일에 대해서 결과값이 같은 엔트리로 매핑되는 해시 함수에서 흔히 발생함.
디렉토리에다가 파일의 메타데이터를 직접 저장할 수 도 있지만 unix, fat에서 보시다시피 전부 디렉토리가 가진게 아니라서 별도 보관하는 곳이 있을 수 있다. inode, fat에 파일 메타데이터를 가졌음.
긴 파일 이름을 지원하는 방식
디렉토리가 파일의 메타데이터를 저장할 때, 어떤건 이름이 길고 짧으면 위치가 들쭉날쭉. 될 수 있다. 그렇게는 안하고 엔트리 크기는 고정해두고 그 위치만 찾으면 되도록 구현. 대부분의 메타데이터들은 길이가 한정되어 있다.
파일 이름은 특정 바이트 수로 제한할 수는 있지만 그렇게 하는건 비효율적ㅇ. 굉장히 긴 이름도 지원을 해줘야 할텐데 엔트리의 크기는 고정되어 있고, 그래서 어떻게 지원할 것인가?
이름에 대한 필드를 무조건 길게 하는 것이 아니라 어느정도 길이로 한정해두고 대단히 길다고 하면 앞부분은 여기다가 저장해두고 포인터를 둬서 이 디렉토리 파일 맨 끝에서부터 파일 이름이 거꾸로 저장되도록 함.
예를 들어서 이름이 aaabb라고 하면 저장이 3글자 + 포인터 1 까지 저장 가능 ⇒ a a a 저장하고 포인터를 주고 b b 저장
짧은 파일 이름은 여기다가 저장하고 맘. 파일이 끝났다는 건 \0로 나타냄.
이렇게 해서 긴 이름의 파일을 디렉토리에서 어떻게 지원하는지 설명 완료~
파일 시스템에 대한 일반적인 구현에 대한 설명 완료~
VFS, NFS
1.
VFS
사용자가 파일 시스템에 접근하려면 시스템 콜을 해야함. 파일 시스템 종류마다 다른 시스템 콜을 써야한다면 혼란스러울 것. 그래서 어떤 파일 시스템이 실제로 사용되는지에 상관업시 개별 퍼ㅏ일 시스템 윗 계층에 VFS라는 인터페이스를 두고 있음. 사용자가 파일 시스템을 사용하는지에 관계없이 VFS 파일 시스템을 사용하게 된다. 다양한 파일 시스템들이 있지만 사용자 입장에서는 동일한 시스템 콜 인터페이스를 통해서 파일 시스템을 접근 할 수 있게 해주는 계층(layer)
2.
NFS
파일 시스템이 로컬에 저장될 수도 있지만 원격에 있는걸 접근할 수도 있다. NFS를 써서 접근. 그림에 컴터 두대가 있음. Client라는 컴터, Server라는 컴터가 있음. 두 대의 컴터가 네트워크로 연결되어 있는 상황. 클라이언특 어떤 파일 시스템이든 상관없이 VFS통해서 접근하는데 로컬 컴터도 가능하고 원격의 다른 컴터 파일 시스템 접근할 수 있는걸 지원. NFS. 여러가지 더 있음. 로컬 사용자가 이 파일 시스템에 접근을 하려면 VFS 인터페이스를 통해서 시스템 콜을 해서 접근을 하면 될 것.
근데 지금은 이쪽에 있는 사용자가 다른 쪽으로 disk 접근하기 위해서 VFS 인페를 써서 마치 자기 컴터 파일 시스템처럼 접근 요청을 보내는 것. 그래서 따라갔더니 내 컴터에 해당 파일 시스템이 없음. 그러면 NFS 파일 시스템이 발동해서 RPC를 통해서 네트워크를 통해서 서버쪽에 접근함. 서버쪽에서도 VFS와 NFS 모듈이 있어서 이 친구가 자기 사용자가 접근하는 것처럼 VFS 사용해서 파일 시스템 접근 요청을 한다. 그러면 구체적인 유닉스 파일 시스템 접근해서 내용을 끄집어 내가지고 client 쪽에 전달을 해줌. 그럼 클라에서 NFS client 모듈이 바당서 사용자한테 전달. 이런 분산 시스템에서 네트워크를 통해 파일 공유. NFS 지원하려면 서버 쪽에도, 클라쪽에도 모듈이 있어서 같은 약속을 가지고 접근할 수 있게 해줌 된다.
PAge Cache은 가상 메모리에서 설명했음. Pageing 시스템에서 사용하는 페이지 프레임들을 페이지 캐시라고 불름. 스왑 에리어 패킹 스토어보다 빠르다. 캐싱의 관점에서 페이징 시스템에서의 페이징 캐시라고 함.
버퍼 캐시는 어떤 파일의 데이터를 사용자가 요청했을 때, 디스크에서 읽어서 사용자한테만 전달하고 마는게 아니고 운영체제가 자기의 영역중 일부에 저장을 해두고 똑같은 파일 데이터를 같은 친구가 요청하면 디스크까지 가는게 아니고 버퍼 캐시에서 읽어다가 주는 방식.
페이지는 가상 메모리 관점, 버퍼는 파일 시스템 관점.
두개는 관리하는 방법 다르다. 페이지는 운영 체제에게 주는 정보가 제한적. 캐시 히트가 나면 이미 메모리에 존재한ㄴ건 하드웨어적으로만 주소 변환을 해서, 접근 시간 같은 걸 알 수가 없어서 클락 알고리즘 같은 거 ㅅㅏ용.
버퍼 캐시는 메모리에 있든, 디스크이 있던간ㄷ에 파일 접귾에는 시스템 콜이 필요해서 운체에게 CPU 제어권이 넘어가고 그 파일에 대한 요청이 언제 일어났는지 캐시, 히트 어떤 것이든 알 수가 있어서 LRU, LFU알고리즘 사용 가능
최근에는 둘을 합쳐서 같이 관리하는 그런 운체가 많음. Linux
그런 구조를 Unified Buffer Cache라고 부른다.
합쳐져 있다는 거가. Buffer cache도 페이지 단위로 관리한다. 운체에서 이런 페이지 프레임(물리적인 메모리)들을 관리하는 루틴에 페이지, 버퍼 캐시를 같이 관리한다는 얘기. 관리하는 방법 다르지 않다.
파일 입출력 방법중에서 버퍼 캐시를 이용하는 read, write를 시스템 콜 사용해서 파일에 접근하는 방법, 메모리 mapped i/o를 이용해서 파일을 접근하는 방법이 있음. 메모리 mapped i/o는 파일을 접근할 때 원래는 오픈해서 read, write를 통해서 접근하는데 그 방법을 안쓰고 파일의 일정 부분을 메모리 영역에다가 매핑을 해두고 쓰는것. 매핑을 해두고 나면 그 다음부터는 read, write 시스템 콜을 하는 게 아니라 메모리에다가 읽고 쓰는, 실제로는 파일에다가 데이터를 읽고 쓰는 효과가 나게 하는 게 메모리 mapped i/o.
물리적 메모리, 사용자 메모리 영역은 페이지 단위로 필요한 데ㅔ이터가 올라가고 내려가고, 원래는 커널 메모리 영역에 버퍼 캐시가 존재. 그래서 어떤 파일의 내용을 읽어오ㅓ라고 하면 이걸 먼저 버퍼 캐시에 가져오고 나서 사용자에게 전달해주는 방식. 페이지는 보통 4KB 단위이고 블록하나는 512byte로 구성.
최근에는 page cache하고 buffer cache가 합쳐졌기 떄문에 버퍼 캐시에서도 4KB 페이지 크기로 블럭들을 관리하고 있음. unified의 특징.
가상 메모리기법에서 쓴느 swap 영역은 빠르게 데이터를 내려놓고 올리고 해야해서 여러개의 블록을 모아서 4KB단위로 올려놓고 내려놓고, 더 크게 여러개의 페이지를 올리고 내리고 함. 속도 효율성을 위해서
파일을 접근하는 방법은 다음 시간에~