File Systems Implementation

Allocation of file data in disk

  • contigous allocation

  • linked allocation

  • indexed allocation

contigous allocation

  • directory 는 파일의 메타데이터를 가지고 있다.

  • 위의 예를 통해서 보면, count 파일은 시작점 0번부터 길이가 2기 때문에 0, 1 에 위치하게 된다.

  • 단점

    • external fragment 외부조각이 발생한다. 외부의 남는 공간이 발생한다.

    • 파일이 수정되었을 때, 파일 크기가 커지는 것에 대비하기가 어렵다.

      • 미리 파일이 커질 수 있는 것에 대비하여 최대 공간만큼 차지하도록 한다.

        • 얼마나 큰 hole 을 할당할 것인가…?

        • 공간 할당이 되지만 쓰이지 않는 내부 조각이 발생할 가능성이 있다.

  • 장점

    • 빠르다

      • 한번의 seek/rotation 으로 많은 바이트 transfer

      • realtime file 용으로, 또는 이미 run 중이던 process 의 swapping 용도로 쓰인다.

        • swapping : 공간 효율성보다는 속도가 훨씬 중요한 경우

    • direct access (=randome access) 가 가능하다.

      • 앞에 선행하는 파일들을 모두 거치지 않아도 내가 보고 싶은 특정한 파일만 볼 수 있다.

linked allocation

  • 파일의 시작위치만 디렉토리가 가지고 있고, 그 다음 위치들은 해당 파일 내에 접근하여 확인할 수 있다.

  • 장점

    • continous allocation 연속할당과 다르게 파일의 길이가 안맞아 사용되지 못하는 외부조각이 발생하지 않는다.

  • 단점

    • 직접접근이 불가하다.

      • 4번째 블록의 내용이 궁금하면 1→2→3→4 순서대로 탐색을 하여 내용을 확인해야 한다.

      • 즉, 건너 뛰는 것이 불가하다.

    • 순차접근에 대해서 탐색 시간이 오래 소요된다.

    • 안정성 측면에도 문제가 있다. reliability

      • 한 sector 에 문제가 생기면 그 이후 포인터의 위치를 알 수 없기 때문에 파일 전체를 접근하지 못하게 된다.

    • 다음 포인터의 위치를 저장하느라고 파일 블록 공간을 차지하기 때문에 온전히 공간을 사용할 수 없다는 문제가 있다.

      • 512bytessector

      • 4bytes/pointer

  • 단점의 보완

    • file-allocation table, FAT 파일 시스템

      • 포인터를 별도의 위치에 보관하여 reliability 와 공간 효율성 문제를 해결한다.

indexed allocation

  • 디렉토리 내에서 index block 의 위치를 가지고 있고

  • 해당 인덱스로 접근하면 모든 파일들의 내용에 접근 가능하다.

  • 장점

    • 순차접근이 아니다. index 만 접근하면 접근하고자 하는 위치에 바로 접근할 수 있다.

    • 외부 공간이 발생하지 않는다.

  • 단점

    • 작은 공간이라고는 하나 index를 위한 블록이 별도로 필요하다. 작은 파일일 경우, 공간낭비가 발생할 수 있다. 그리고 실제로 많은 파일들은 그 크기가 작다.

    • 또 너무 큰 파일의 경우는 하나의 블록으로 index 를 저장하기에 부족하다.

      • linked scheme 을 사용한다. index 공간이 부족해지만 가장 마지막 줄에 2번째 index 의 위치를 남긴다. 그러면 순차적으로 다음 index 로 접근이 가능하다.

      • multi level index 를 사용한다. 2단계 페이징 테이블처럼 index 안에 다른 index 의 위치를 나열한다.

위의 세 가지 할당 방법은 모두 이론적인 것이다. 그렇다면 실제로는 어떤 식으로 파일 데이터를 저장하고 보관하고 있을까

UNIX 파일 시스템의 구조

  • boot block

    • 모든 컴퓨터의 파일시스템에 동일하게 첫번째로 존재한다.

    • 부팅에 필요한 정보, bootstrap loader

  • super block

    • 파일 시스템에 관한 총체적인 정보를 담고 있다.

      • inode 의 길이, 시작점 등

  • inode list

    • inode = index node

    • 파일 하나 당 1개의 inode 가 할당된다.

    • 실제 파일 시스템에서는 디렉토리가 모든 파일의 메타데이터를 가지고 있지는 않는다. 실제 파일의 메타데이터들은 별도의 공간에서 관리를 하고 있는데, 그 공간이 바로 inode list 이다.

    • 파일 이름을 제외한 파일의 모든 메타데이터는 이곳에 저장되어있다.

    • 적은 inode 공간으로 효율적인 파일 데이터 접근 관리

      • direct block : 바로 파일데이터로 접근 가능

      • single indirect : 한번 index 를 거쳐서 데이터에 접근 가능

      • double indirect

      • triple indirect

  • data block

    • 파일의 실제 내용을 보관한다.

    • 파일의 메타데이터 중, 제목을 가지고 있다.

    • directory file : <file 이름 + inode 번호> 형태로 이루어져있다.

FAT file system

  • boot block

  • FAT

    • 파일의 메타데이터 중 위치정보를 FAT 이 가지고 있다.

    • data block 의 개수만큼 존재한다.

  • root directory

  • data block

    • 파일의 메타데이터 중 위치정보를 제외한 모든 정보를 directory 가 가지고 있다.

    • directory file : <file 이름 - FAT 시스템 번호>

  • 장점

    • 직접접근이 가능하다. FAT 파일 시스템 내부의 번호 연결만 따라가면 직접 data block 에 접근하여 열어보지 않아도 직접 원하는 파일에만 접근이 가능하다.

    • 한 sector 가 고장나서 pointer 가 유실되더라도 FAT 내부에 위치정보가 있으니 reliability 가 보장된다.

위의 두 가지 파일시스템의 구조만 보았지만, 실제로는 다양한 구조들이 존재하고 변형되어 쓰인다.

Free-space management

  • bit map/bit vector

  • linked list

  • grouping

  • counting

bit map/bit vector

  • 0, 1로 블록이 사용중인지 표시한다.

  • 단점 : 디스크 내부의 부가적인 공간을 필요로 한다.

  • 장점 : 연속적인 n개의 free block 을 찾는데 효과적이다.

linked list

  • 모든 free block 들을 링크로 연결한다. free list

  • 연속적인 가용 공간을 찾는 것이 쉽지 않다.

    • 따라서 현실에서 사용하기에는 쉽지 않다.

  • 하지만 공간의 낭비가 없다.

grouping

  • linked list 방법의 변형

  • 첫번째 free block 이 n개의 포인터를 가진다.

    • n-1 pointer 는 free data block 을 가리킨다.

    • 마지막 pointer 가 가리키는 block 은 또다시 n pointer 를 가진다.

counting

  • 프로그램들이 종종 여러개의 연속적인 block 을 할당하고 반납한다는 성질에 착안한다.

  • (first free block, 연속적인 free blocks) 쌍 형태로 관리한다.

directory implementation, 디렉토리는 어떻게 구현되는가

  • linear list

  • hash table

linear list

  • <file name, file metadata> 의 list

  • 구현이 간단하다.

  • 디렉토리 내에 파일이 잇는지 찾기 위해서는 linear search 가 필요하다.

    • time-consuming

hash table

  • linear list + hashing

  • hash table은 파일 이름을 이 파일의 linear list 의 위치로 바꾸어준다.

  • search time 을 없앴다.

  • collision 이 발생할 가능성이 있다.

    • 서로 다른 결과값이 같은 entry 로 매핑되는 문제

    • hash 함수에서 흔히 발생하는 문제

file metadata 보관위치

  • 디렉토리 내에 직접 보관하는 방법과

  • 디렉토리에는 포인터를 두고 다른 곳에 보관하는 방법

    • inode, FAT 등

Long file name 지원

  • <file name, file의 메타데이터>의 list 에서 각 entry 는 일반적으로 고정 크기

  • file name 이 고정 크기의 entry 길이보다 길어지는 경우, entry 의 마지막 부분에 이름의 뒷부분이 위치한 곳의 포인터를 두는 방법

  • 이름의 나머지 부분은 동일한 directory file 의 일부에 존재한다.

VFS and NFS

VFS, virtual file system

  • 서로 다른 다양한 file system 에 대해 동일한 시스템 콜 인터페이스 api 를 통해 접근할 수 있게 해주는 OS layer

NFS, network file system

  • 원격에 저장되어있는 파일 시스템에 접근을 해야하는 경우

  • 분산 시스템에서는 네트워크를 통해 파일이 공유될 수 있다. NFS는 이러한 분산환경에서 대표적으로 파일을 공유하는 방법이다.

  • 서버와 클라이언트 모두 NFS 모듈이 있어야 한다.

    • NFS client

    • NFS server

page cache vs. buffer cache

page cache

  • virtual memory 의 paging system 에서 사용하는 page frame 을 caching 의 관점에서 설명하는 용어

  • memory-mapped i/o 를 쓰는 경우, file 의 i/o 에서도 page cache 를 사용한다.

buffer cache

  • 파일 시스템을 통한 i/o 연산은 메모리의 특정 영역인 buffer cache 를 사용한다.

  • 파일 사용의 locality 를 활용한다.

    • 한번 읽어온 block 에 대한 후속 요청 시, buffer cache 에서 즉시 전달한다.

  • 모든 프로세스가 공용으로 사용된다.

  • replacement algorithm이 필요하다. LRU, LFU 등

unified buffer cache

  • 최근의 OS 에서는 기존의 buffer cache 가 page cache 에 통합된다.

  • buffer cache 를 위한 별도의 공간을 분리해두지 않고, page cache 에서 필요할 때마다 할당해서 쓴다.

  • unified buffer cache 를 이용하지 않을 때

    • I/O read() & write() 를 실행하면, buffer cache를 거쳐서 캐시 내 존재하면 바로 응답하고, 없다면, file system 에서 가져와 buffer cache 에 등록한 뒤, 응답해준다.

    • memory-mapped I/O 를 실행하면, page cache 를 일단 검사한 뒤, 없다면 buffer cache 를 검사하고, 그곳에도 없을 때, file system 에 접근하여 가져온다.

  • unified buffer cache 를 이용할 때

    • 통합된 버퍼 캐시를 사용할때는 이러한 과정이 보다 단순해진다.

    • page cache 를 buffer cache 로 쓰기 때문에 실행 프로세스가 한결 간단해진다.

memory-mapped i/o

  • file의 일부를 virtual memory 에 mapping 시킨다.

  • 매핑시킨 영역에 대한 메모리 접근 연산을 통해 파일의 입출력을 수행할 수 있다.

  • 위의 그림에서 보면, 프로세스 내부의 code 영역이 memory-mapped i/o 를 사용하는 가장 대표적인 예이다.

    • 프로세스가 실행될 때, 물리적 메모리로 로드되고, 프로세스가 스위칭 되면, 대부분의 데이터는 swap area 로 이동하여 임시 보관된다.

    • 하지만 code 영역은 이미 실행파일 자체에서 모든 것이 쓰여진 완성된 형태의 read only 영역이다. 따라서 프로세스가 스위칭 되는 당시의 상태를 저장하는 swap area 에 저장할 필요가 없이, virtual memory 자체에 매핑되어 읽으면 된다.

    • virtual memory 에 없는 내용일 경우, 페이지 폴트가 발생할 것이다. file system 인 실행파일에서 필요한 코드의 내용을 또 일정부분 불러와 virtual memory 와 매핑시켜 읽으면 된다.

결국, 사용자가 file system 에 접근하는 방법에는 두 가지 인터페이스가 있다.

  1. I/O read() & write() 함수를 이용하는 경우이고,

  2. memory-mapped I/O 를 이용하는 경우이다.

I/O read() & write() 함수를 이용하는 경우

unifed buffer cache 에서 1번을 이용할 경우에는 physical memory 에 매핑된 데이터 자체가 이미 buffer cache 이므로, 요청된 내용이 존재하면 그 부분을 copy 하여 프로세스에게 응답한다. 기존 물리적 메모리에 있는 정보를 매핑하는 것이 아니라 복사해서 전달하기 때문에, 데이터 일관성 문제가 발생할 여지가 없고 운영체제가 중간에 항상 중재를 하기 때문에 관리에 좀 더 수월하다는 장점이 있다.

memory-mapped I/O 를 이용하는 경우

2번일 경우에는 physical memory 에 올려져있는 데이터를 virtual memory 에 매핑하여 사용한다. 이 경우, 일단 메모리에 올려진 데이터는 운영체제를 시스템 콜로 호출하지 않고 자신의 메모리 영역 내에서 응답할 수 있기 때문에 빠르고 물리 메모리에서 나의 가상 매모리로 데이터를 복사하는 시간이나 노력을 들이지 않을 수 있다.

단점이 있다면, physical memory 를 다른 프로세스들과 공유해서 이용하므로, 데이터의 일관성 문제가 발생할 수 있다.

Last updated