reference: https://pages.cs.wisc.edu/~remzi/OSTEP/, 시스템 프로그래밍, 운영체제 수업(최종무 교수님)
파일 시스템은 자신이 관리하고 있는 파티션(partition)내 free block들을 관리하고 있다가 요청이 들어오면 파일을 위한 공간을 할당해준다.
파일!
모든 자원을 파일로써 취급하는 것은 리눅스 파일시스템의 고유한 특성이다.
파일은 이름이 존재하고, 이 이름이라는 속성으로 추상적인 객체인 파일에 접근할 수 있는 것이다.
다르게 표현하자면, '(파일의 )이름'을 입력 받아 해당 데이터를 제공해주는 소프트웨어가 파일시스템인 셈이다.
할당 방법에는 크게 연속 할당(sequential allocation)과 불연속 할당(non-sequential allocation)이 있다.
연속 할당은 불연속 할당보다 파일을 읽는 속도가 빠르다는 장점이 있지만 파일 크기가 변하는 추가(append) 과정에서는 성능면에서 불연속 할당보다 취약하다. 예를들어 파일에 append하는 작업이 필요하지만 연속적으로 블록을 할당하지 못하는 경우가 발생한다면 기존에 있던 블록들을 다른 곳으로 복사하는 과정이 필요하다. 이 과정은 성능 상 매우 큰 문제가 된다. 따라서 파일시스템 설계 시 연속 할당만을 사용하는 경우는 거의 없다.
불연속 할당은 파일에 속한 데이터들을 디스크 블록에 연속적으로 저장하지 않는다. 따라서 위에서 언급한 append 작업을 통한 성능 하락 요인이 발생하지 않는다. 하지만 이 할당 방식에서는 파일에 속한 디스크 블록들이 어디에 위치하는지에 대한 정보를 기록하고 있어야 한다. 이를 위한 방법으로는 대표적으로 앞선 포스팅에서 살펴본 inode 자료구조 기법(인덱스 블록 활용)이 있고, 이 외 블록체인 기법, FAT 기법등이 있다. 대표적으로 FAT 기법에 대해 간략히 설명하자면 아래와 같다.
같은 파일에 속해 있는 블록들의 위치를 FAT이라는 자료구조에 기록해 놓는 방법. 파일시스템이 관리하는 파티션 내 전역적으로 존재하는 FAT 구조를 사용한다.
인덱스 블록 기법은 파일 마다 인덱스 블록이 필요하지만, FAT 기법에서는 파일시스템 전체적으로 하나의 FAT이 존재한다.
FAT 구조에서는 'end-of-file'은 파일의 끝을 의미하며 0은 free 상태를 의미한다. 위 그림의 예에서 파일이 가리키고 있는 FAT 구조의 217번(데이터 블록 넘버)을 읽어 보면, 다음 데이터 블록인 618번을 가리키고 있으며, 618번을 가면 다시 다음 데이터 블록 위치인 339를 가리키고 있다. 그리고 339번 위치로 간다면 해당 데이터 블록이 파일의 끝임을 알 수 있다.
이 기법은 블록체인 기법과 달리 파일의 중간 데이터를 읽기 위해 처음 블록부터 읽을 필요가 없다.
다만 FAT 구조의 손실은 파일시스탬 내의 모든 파일 소실의 문제로 직결될 수 있다(단점). 따라서 이러한 문제를 방지하고자 FAT 구조 파일시스템은 FAT 내용을 중복으로 관리한다.
FAT 파일시스템에서 메타데이터는 FAT 테이블, 디렉터리 엔트리, 슈퍼블록으로 구성된다.
디렉터리 엔트리
struct msdos_dir_entry { _u8 name[MSDOS_NAME]; // 파일의 이름과 확장자를 담는 필드 _le17 time, date, start; // 시간정보, 데이터 블록 중 "첫 번째 블록 번호"(start)(FAT 테이블 참조 시작점) _le32 size; // 파일 크기 ... ... };
위 코드는 대표적인 FAT 파일시스템인 msdos의 디렉터리 엔트리 구조이다. 각 파일마다 디렉터리 엔트리를 하나 씩 갖는 msdos 파일시스템에선 디렉터리 엔트리를 모아 하나의 디렉터리로 구성한다.
리눅스에서 디렉터리와 파일은 별도 구분이 없다. 디렉터리는 자신이 포함하는 파일의 이름들을 데이터로 갖는 하나의 파일에 불과하다.
다른 파일시스템의 디렉터리 엔트리 또한 자신들만의 디렉터리 구조체(struct dir_entry)를 선언하고, 파일이 생성될 때 이 구조체에 파일 관련 내용(이름, 속성, 블록 위치 등)을 저장하고 디스크에 저장한다. 이 후 사용자가 특정 파일을 요청하면 해당 파일의 이름을 통해 디렉터리 엔트리를 찾은 후 디렉터리 엔트리에 포함된 정보를 통해 데이터 블록을 찾아가 그 내용을 다시 사용자에 제공한다.
슈퍼블록은 최상위의 디렉터리(루트, /) 첫 번째 블록 번호를 적어두는 공간이다. 이를 통해 언제라도 루트 디렉터리부터 시작하여 다른 파일들을 찾아갈 수 있다.
슈퍼 블록(metadata for file system)
struct msdos_sb_info { unsigned short sec_per_clus; // 클러스터 당 섹터의 갯수 unsigned int cluster_size; // 클러스터 크기 unsigned long fat_length; // FAT 테이블 위치와 크기 unsigned long root_cluster; // '/'의 첫 번째 데이터 블록 위치 ... ... };