[운영체제] 파일시스템
현재 글은 Operating System ConceptsTenth Edition 의 슬라이드 내용을 기반으로 하고 있습니다. 단, 본문의 내용이 반드시 해당 서적의 내용을 보장하지는 않으므로 필요하다면 직접 책을 찾아 읽는 것을 추천합니다.
링크 : https://www.os-book.com/OS10/
파일
논리적 주소 공간에 연속하여 존재하는 데이터 덩어리로, 운영체제에 의해 물리적 주소에 매핑된다.
- 타입
- 데이터 타입 : Numeric, Character, Binary ...
- 프로그램 : 특정 명령을 수행하는 바이너리 코드 등
파일의 컨텐츠는 파일 생성자에 의해 정의되며, 정말 다양한 목적으로 사용될 수 있기 때문에 text, source, executable 등 다양한 타입을 가질 수 있다는 특징이 있다.
파일의 속성(Attribute)
- name : 인간이 특정 파일을 인식하는데 필요한 이름 정보
- Identifier : 파일 시스템 내에서 파일을 식별하는데 사용되는 고유한 태그
- Type : 파일이 수행하는 역할에 따른 타입 정보. 파일은 순수한 텍스트, 실행 파일, sh 파일, 게임 정보, exe, 오브젝트 등 정말 다양한 역할을 가지는데, 운영체제에게 이런 역할을 인식시키기 위해서는 파일 타입(확장자)가 필요하다.
- Location : 디바이스 상에 파일이 실제로 위치한 장소에 대한 포인터
- Size : 현재 파일의 사이즈. 최대 허용가능한 사이즈로 나타날 수도 있다.
- Protection : Read/Write/Execute에 대한 권한 정보
- Time, Date, User Identification .... : 수정 시간, 날짜 및 유저 정보 등도 존재.
- extended file attributes ( 인코딩, 보안-체크섬 ) ...
파일에 관한 정보는 디렉토리 구조에 포함된다. 일반적인 운영체제에서는 디렉토리를 통해 파일에 접근할 수 있다. 이게 가능한 이유는 디렉토리가 각 파일에 대한 일종의 링크를 가지고 있기 때문이다.
각각의 파일마다 언급된 속성 말고도 다양한 속성을 목적에 맞게 가질 수 있다.
파일의 동작(Operation)
일반적으로 생각할 수 있는 파일에 대한 동작이 포함된다.
- Create : 파일을 생성하는 동작.
- 파일을 위한 충분한 공간이있는지 검사한다.
- 파일의 엔트리가 디렉토리 내에 있는지 검사한다.
- Write
: 특정 파일에 대한 핸들(포인터)을 열고, 해당 공간에 내용을 작성한다. - Read
: 특정 파일에 대한 핸들(포인터)을 열고, 해당 파일의 내용을 읽어온다. - Reposition
: 파일 핸들의 위치를 이동시키거나, 특정 요소를 찾는다. 파일 디스크립터는 메모리 상에 파일을 올려두므로 I/O가 반드시 동반될 필요는 없다. - Delete
: 파일 위치와 관련된 경로를 날린다. Delete을 수행했다고 해당 파일이 실제로 지워졌다고 보장할 수는 없다. 우리가 생각하는 삭제 동작은 해당 공간이 다른 파일로 덮어씌워질 때 발생한다. - Truncate
: 파일을 삭제하지는 않고 내용을 지우는 경우. 파일 속성 정보는 그대로 두고 내용만 제거한다. - Open
: 파일을 여는 동작으로, 파일 디스크립터를 얻는다. Open을 수행하면 일반적으로 해당 파일이 메모리에 적재되므로 읽거나 쓰는 대상은 디스크가 아닌 메모리가 된다. 따라서 해당 내용을 실제 디스크 상에 저장하고 싶다면 특별한 명령을 수행하거나 파일을 Close을 통해 닫아야 한다. - Close : 메모리 상에 존재하는 파일 내용을 실제로 디스크에 반영하는 동작이다. Open과 쌍을 이룬다.
Opening Files
일반적으로 Write은 파일을 읽고 있는 프로세스가 단 하나밖에 존재하지 않을 때 수행된다. 이 동작을 위해서는 특정 파일을 어떤 프로세스가 읽고 있는지 정보가 필요하므로, 어딘가에는 해당 정보를 저장해야만 Write을 수행할 수 있다.
- Open-file table : 현재 어떤 파일이 열려 있는 지 등의 정보를 저장하는 테이블.
- File-Open count : 특정 파일이 프로세스에 의해 얼마나 open 되어 있는지 정보를 유지하는 카운터
물론 다음과 같은 정보들도 필요하다.
- Location of the file
: 실제 파일의 위치. 파일을 open 하면 성능상의 문제로 메모리 혹은 캐시를 활용하여 실제 파일과 대응되지 않는 메모리 상의 객체를 가리킬 수 있으므로, 특정 내용을 읽거나 쓰기 위해서는 실제 파일의 위치 정보가 필요할 수 있다. - Access rights
: 파일에 대한 접근 권한. 각각의 파일에 대한 테이블을 부여하여 OS가 요청을 허가하거나 거부할 때 사용된다.
File Locking
파일에 대해 읽기만 가능하는 등 경우에 따라 강제적 혹은 묵시적인 lock이 필요한 경우가 있다. 예를 들어 특정 프로세스가 파일을 Write 하고 있다면 데이터 일관성을 위해 다른 프로세스의 Read 권한을 막아야 한다. 이런 동작을 위해 몇가지 lock을 지원하기도 한다. 운영체제마다 다를 수 있다.
- Shared Lock : reader lock 과 유사. 여러 프로세스가 동시에 요청 가능하다.
- Exclusive Lock : writer lock 과 유사. 한 순간에 하나의 프로세스만이 배타적으로 사용할 수 있도록 보장한다.
다음과 같은 file locking 메커니즘을 제공하기도 한다.
- mandatory
: 어떤 프로세스가 exclusive lock을 요청하면 OS는 다른 프로세스가 locked file 에 접근할 수 없도록 막는다. - advisory
: 운영체제는 다른 프로세스의 접근을 막지 않는다. lock status 정보가 존재하며, 해당 정보를 기반으로 하여 소프트웨어 상에서 알아서 data integrity을 보장 한다.
File Types
파일은 정말 다양한 용도를 가지고 있다. 운영체제는 각각의 파일의 용도를 인식하고, 대응되는 동작을 수행하게 된다. 이때 해당 파일이 어떤 용도인지 정보는 파일 코드 자체에 내장될 수도 있지만 일반적으로는 파일의 이름에 확장자를 함께 표현하는 방식으로 간단하게 구현된다.
일부 확장자는 OS 자체적으로 인식할 수 있다. 반대로 나머지 확장자들은 특정 프로그램의 목적에 맞게 해석되기 위해 만들어진 타입이므로 OS 대신 해당 프로그램 선에서 해석하게 된다.
결국 확장자는 OS 혹은 프로그램에게 현재 파일이 어떤 타입인지에 대한 정보를 제공하는 힌트 역할을 한다.
File Structure
파일은 다양한 구조를 가질 수 있다.
- None : 딱히 구조가 없는 경우. sequence of words / bytes
- Simple Record Structure : 간단한 레코드 기능 ex ) Lines / Fixed Length / Variable Length
- Complex Structures : 복잡한 정보를 담은 경우
- Formatted document
- Relocatable load file
결국 파일을 해석하는 주체는 운영체제 혹은 프로그램이므로 해당 대상들은 전부 블럭 단위로 처리하거나 연관된 포맷과 연결하여 해석하는 등 다양한 선택지를 기반으로 동작할 수 있다.
Access Method
특정 파일의 정보에 접근할 때는 여러가지 방식의 접근 방식이 존재할 수 있다.
Sequential Access
파일을 처음부터 끝까지 순차적으로 탐색하는 방식이다. 이전 내용을 읽으려면 rewind을 수행하고, 특정 데이터를 찾으려면 해당 위치까지 position을 옮겨야 한다. 과거 테이프와 같은 저장소에서의 정보 접근 방식과 유사하다. 마치 배열을 순차 탐색하듯 동작하기 때문에 특정 위치를 지정하여 읽지는 못한다.
- read next : 다음 내용을 읽는다.
- write next : 다음 내용을 쓴다.
- Reset : 현재 위치를 초기화한다.
Direct Access
원하는 위치를 바로 찾아가는 방식이다. 디스크에서 원하는 실린더로 이동하는 경우 (seek time) 및 SSD에서 random access을 통해 바로 특정 위치를 읽거나 쓰는 방식에 대응된다고 생각해볼 수 있다.
각 위치는 상대적인 블럭 주소 ( relative block number ) 를 이용하여 나타내며 파일의 시작 인덱스를 0으로 잡는 방식이 압도적으로 많이 사용된다. 해당 인덱스 자체는 실제 저장된 주소와 큰 상관이 없다.
- read n
- write n
- position to n
- read next
- write next
- rewrite n
Other Access Methods
특정 경우에는 자주 사용하는 파일에 대해 인덱스를 만들어 두고 해당 인덱스를 기반으로 바로 접근하도록 구현하기도 한다. 해당 인덱스는 메모리 상에 유지되며 전체 블럭을 탐색하기 이전에 인덱스를 이용하여 특정 블럭의 위치를 얻을 수 있는지 체크한다.
파일이 너무 큰 경우에는 인덱스 파일은 디스크에 저장하고 이를 위한 인덱스를 메모리에 저장하여 관리하기도 한다.
Disk Structure
하나의 디스크는 여러개의 파티션 단위로 나뉘어 RAID 등의 시스템에 의해 관리된다. 각각은 파일 시스템 없이 원시적인 형태로 사용되거나, 특정 파일 시스템 형태로 포매팅 되어 사용될 수 있다.
논리적 디스크 장치를 volume이라고 한다. 예전에는 하나의 HDD을 다양한 단위로 파티션하여 C: , D: 로 사용하기도 했다. 실제 물리적 디스크는 하나로 구성되지만 논리적 단위로는 2개로 파티션하여 사용되었던 것이다. 물론 여러개의 디스크가 하나의 파티션으로 합쳐져서 취급될 수도 있다.
파일 시스템을 가지고 있는 각각의 볼륨은 device directory 혹은 volume table of contents 안에 파일 각각의 파일 시스템 상의 디렉토리 및 파일을 추적하는 구조를 가진다.
다양한 파일 시스템이 존재하며, 이러한 파일 시스템들이 하나의 OS 내에서 함께 사용되기도 한다. FAT32, NFS 등 과거 USB 크기 인식 문제가 있었을 때 파일 시스템을 선택할 수 있었던 것도 이에 대한 증거 중 하나다.
Directory
디렉토리, 흔히 우리가 폴더라고 부르는 자료구조는 자신이 보유한 파일에 대한 일종의 포인터를 가지는 자료구조로, 디렉토리 및 파일 둘 다 디스크 상에서 관리된다. 현재 사용되는 대부분의 운영체제는 디렉토리 기반으로 동작한다. 예를 들어 윈도우 운영체제에서 주된 파일은 모두 C 드라이브 아래에 존재한다. 전체를 디렉토리 구조라고 생각하면 윈도우 운영체제의 파일 시스템은 C 를 루트 디렉토리로 하는 모든 nested 디렉토리 및 파일 형태를 띈다고 볼 수 있는 것이다.
디렉토리 구조 사용의 목적은 다음과 같다.
- Efficiency
: 특정 파일의 위치를 빠르게 찾을 수 있어야 한다. - Naming
: 다양한 유저가 있을 때 하나의 이름을 하나의 유저만 사용할 수 있는 것은 불편하다. 따라서 모든 유저가 동일한 이름의 파일들을 소유할 수 있게 되는 것이 더 현실적일 것이다. - Grouping
: 목적 및 분류에 따라 파일들을 그룹지어서 관리할 수 있도록 지원해야 한다.
디렉토리의 동작 (Operation)
- Search for a file
- Create a file
- Delete a file
: 파일 시스템에서 언급했듯이 파일이 적힌 기록 자체를 바로 삭제하지는 않고, 파일에 대한 링크만 제거한다. - List a Directory
- Rename a file
- Traverse the file system
디렉토리의 구조
Single-Level Directory
디렉토리가 단 하나의 계층만을 가지는 형태로, 모든 유저가 동일한 하나의 디렉토리를 사용하게 된다.
- 파일의 위치는 바로 찾을 수 있다.
- 모든 파일은 제각기 다른 이름을 가져야 한다 ( Naming 문제 )
- nesting 디렉토리가 존재하지 않으므로 파일을 의도에 따라 따로 보관할 수 없다 ( Grouping 문제 )
Two-Level Directory
디렉토리가 2개의 계층을 가지는 형태로, 각 유저마다 개별 디렉토리를 사용하게 된다.
- 개개 유저의 이름은 일종의 path로 동작하며, 해당 디렉토리 안에 개인의 파일이 존재한다.
- 다른 유저들 사이에 동일한 이름의 파일들이 존재할 수 있다.
- 유저 단위로 파일이 구분되기는 했지만, 여전히 파일을 의도대로 분리할 수는 없다.
Tree-Structured Directories
디렉토리를 일종의 트리 구조로 구현한 것이다. 효율적인 작업 및 검색이 가능하며, 드디어 그룹핑이 지원되므로 '현재' 위치하는 디렉토리 개념이 생겨 디렉토리를 오가는 등의 동작을 수행할 수 있게 된다.
서브 디렉토리를 만들어 파일들을 관리할 수 있다. 루트(관리자) 중심의 디렉토리와 사용자 중심의 디렉토리가 구분되어 따로 사용되며, 일부 공유되는 파일들은 share 디렉토리에 포함되어 모든 유저들이 함께 사용하기도 한다.
모든 디렉토리는 루트 기준 모두 고유하게 표현할 수 있으며, path의 개념도 등장한다.
- Absolute path : 루트를 기준으로 한 경로
- Relative path: 현재 디렉토리를 기준으로 결정하는 경로