파일시스템이란?
우리가 자연스럽게 사용하고 있는 파일과 디렉토리를 관리하는 OS 의 내부 프로그램으로 파일과 디렉토리를 보조기억장치에 일목요연하게 저장(할당)하고, 접근할 수 있도록 해준다. 당연하게도 한 컴퓨터 내에서 여러 개의 파일 시스템을 사용할 수 있다.
파일고 디렉토리는 데이터의 관점으로 보면 보조기억장치에 저장된 데이터 덩어리 그 자체이며, OS 에서 이 덩어리를 파일과 디렉토리로써 일목요연하게 관리를 해주는 것이다.
[파일]
- 보조기억장치에 저장되어 있는 의미있는 정보들을 모은 논리적 단위
( 관련있는 정보들을 한 곳에 모아둔 단위로 이해하면 된다.)
- 파일에는 파일을 실행하기 위한 정보, 파일을 구성하고 있는 정보, 부가 정보(속성 or meta data) 들이 존재한다.
(흔히 window 에서 파일을 마우스 우측클릭으로 속성 버튼을 클릭했을 때 나오는 파일의 날짜나 위치 등등이 meta data 라고 보면된다.)
참고로 meta data 란 어떠한 정보(또는 데이터)를 설명해주기 위한 데이터라고 이해하면 된다.
파일의 속성에서서 보여주는 정보들은 OS마다 조금씩 상이하지만 대표적으로 몇가지 공통적인 정보를 제공해주는 것들이 있다.
파일 유형 - OS가 인지하는 파일의 종류를 나타댄다 (= 확장자)
파일 유형 | 대표적인 확장자 |
실행 파일 | 없는 경우, exe, com, bin |
목적 파일 | obj, o |
소스 코드 파일 | c, cpp, cc, java, asm, py |
워드 프로세서 파일 | xml, rlf, doc, docx |
라이브러리 파일 | lib, a, so, dll |
멀티미디어 파일 | mpeg, mov, mp3, mp4, avi |
백업 / 보관 파일 | rar, zip, tar |
(파일명이 같을지라도 확장자에 따라 실행 양상이 달라지기 때문에 이를 명시화하여 쉽게 구분하기 위해 확장자를 사용한다고 볼 수 있다.)
파일 크기 - 파일의 현재 크기와 허용 가능한 최대 크기
파일 보호 - 어떤 사용자가 해당 파일을 읽고, 쓰고, 실행할 수 있는지의 여부 정보
생성 날짜 - 파일이 생성된 날짜
마지막 접근 날짜 - 파일에 마지막으로 접근한 날짜
마지막 수정 날짜 - 파일이 마지막으로 수정된 날짜
생성자 - 파일을 생성한 사용자
소유자 - 파일을 소유한 사용자
위치 - 파일의 보조기억장치상의 현재 위치
파일을 다루는 모든 작업들은 전부다 OS 에 의해서 이루어진다. 즉, 어떤 응용프로그램도 임의로 접근이나 조작할 수 없으며, 파일을 다루려면 OS 에게 시스템 호출(system call)을 통해서 요청을 해야된다.
OS 에서 파일 연산을 위한 시스템 호출 방식은 다음과 같은 것들이 있다.
파일 생성
파일 삭제
파일 열기
파일 닫기
파일 읽기
파일 쓰기
등등
[디렉토리]
- Window 에선 폴더라고도 불리는 이 디렉토리는 시간을 거쳐가면서 여러 단계들이 생성이 되었는데 최초의 디렉토리는 '1단계 디렉토리'로 하나의 디렉토리 하위에 여러개의 파일들이 존재하는 구조였었다.
- 현재는 컴퓨터의 용량이 커짐으로써 디렉토리 안에 서브 디렉토리, 디렉토리 아래 디렉토리 같이 여러 계층적으로 구성되어 있는것이 보편적이다.
- 이를 트리 구조 디렉토리라고 한다.
그림상에서 볼 수 있는 최상단의 디렉토리는 루트 디렉토리(Root Directory)라고 부른다.
(UNIXS, LINUX, MacOS 시스템에서의 루트 디렉토리는 슬래쉬( / ) 로 표현하며, Window 에선 C:₩ 로 표현한다.)
이렇게 계층적인 구조를 가지다 보니 자연스럽게 <경로> 라는 개념이 생긴것이다.
경로는 디렉토리를 이용해서 파일이나 디렉토리의 위치, 나아가 이름까지도 특정 지을 수 있는 정보이다.
이미 많은 사람들이 알고 있듯이, 동일한 디렉토리에는 같은 파일 이름(확장자까지 같은)은 사용할 수 없고, 서로 다른 디렉토리에는 같은 파일의 이름이 존재하는 것이 가능하다.
위에서 잠시 언급함 경로에는 두가지 개념이 존재한다
절대경로 - 루트 디렉토리에서 해당 파일이나 디렉토리까지 이르는 고유한 경로
상대경로 - 현재 디렉토리에서 해당 파일이나 디렉토리까지 이르는 경로
위의 그림에 있는 내용으로 예시를 들자면 현재 내가 열어놓은 디렉토리가 usr 디렉토리이고, local 디렉토리 내부의 bin 디렉토리의 경로를 표현할 때
절대경로 => /usr/local/bin (제일 처음 사용한 / 는 루트 디렉토리를 의미)
상대경로 => /local/bin (제일 처음 사용한 / 는 단순 경로 표현을 의미)
디렉토리도 파일과 마찬가지로 OS 를 거치지않고 임의로 조작, 접근이 불가능하다.
OS 에서 디렉토리 연산을 위한 시스템 호출 방식은 다음과 같은 것들이 있다.
디렉토리 생성
디렉토리 삭제
디렉토리 열기
디렉토리 닫기
디렉토리 읽기
등등
[디렉토리 엔트리]
위에서 설명한 내용에 따르면 파일과 디렉토리는 엄연히 다른 것으로 표현되는데 사실 디렉토리는 대부분의 OS 에선
<포함된 정보가 조금 특별한 파일> 로 취급하고 있다.(디렉토리 또한 파일이란 셈...)
파일이 파일 정보를 담고 있다면, 디렉토리는 디렉토리가 가지고 있는 대상과 관련된 정보들이 담겨있다.(이 정보들은 보통 테이블(표) 형태로 구성되어 있다)
예를 들자면
파일이름 | 위치를 유추할 수 있는 정보 |
이런 형태이고, 엔트리 = 각 행에 담기는 정보라고 보면 된다. (디렉토리 내에 존재하는 파일의 이름과, 해당 파일의 위치를 유추 할 수 있는 정보로 구성)
나아가 OS 마다 담기는 정보들이 상이하며, 하단 처럼 파일의 속성도 포함시켜서 정보를 제공해주는 경우도 있다.
파일이름 | 위치를 유츄할 수 있는 정보 | 생성시간 | 수정된 시간 | 크기 | ... |
이를 위의 경로 사진의 내용을 참고해서 설명하자면
home 디렉토리 테이블
파일이름 | 위치를 유추할 수 있는 정보 |
.. (상위 폴더를 의미) | |
. (현재 폴더를 의미) | |
user | |
omega |
.. 은 루트 디렉토리 외 모든 디렉토리에서 상위 디렉토리를 가리키며
. 은 모든 디렉토리의 현재 위치를 가리킨다
[파티셔닝]
- 저장 장치의 논리적인 영역을 구획하는 작업으로 목적에 따라 각 영역별로 파일을 저장할 수 있도록 나눠주는 작업이다.
[포매팅]
- 저장 장치에서 사용할 파일 시스템을 설정하는 것으로 어떤 방식으로 파일을 저장하고 관리할 것인지 결정하고, 새로운 데이터를 쓸 준비를 하는 작업으로 포매팅을 통해서 해당 저장 장치의 파일 시스템이 결정된다.
저수준 포매팅 - 제조 공장에서 이뤄지는 물리적인 포매팅
논리적 포매팅 - 파일 시스템을 생성하는 포매팅
파티셔닝과 포매팅되지 않은 저장 장치에 파일을 생성하려고 하면 포매팅 에러 신호를 보내준다.
파티셔닝된 각 영역들은 개별의 파일 시스템을 적용시킬 수 있다. (파티션 구역마다 서로 다른 파일 시스템을 적용시킬 수 있다)
파티셔닝과 포매팅이 동시에 진행될 수도 있고, 제조 공장에서 이미 적용시킨 후에 출고되는 경우도 있다.
[파일 할당]
- 파일과 디렉토리는 하드디스크에 <블록> 단위로 읽고 쓰게된다. 하드 디스크의 가장 작은 저장 단위는 <섹터>이지만, 파일을 표현하기엔 단위가 너무 작고, 개수가 많아 파일 시스템이 모든 섹터를 관리하기 어려워 OS 는 <하나 이상의 섹터를 블록 단위로 묶은 뒤 불록 단위로 파일과 디렉토리를 관리>한다.
연속 할당 - 보조기억장치 내 역속적인 블록에 파일을 할당하는 방식
파일 a, b, c, d, e 가 있을 때 파일 a 의 블록 길이만큼 저장 후 바로 다음 파일 b 의 블록 길이만큼 저장하고, 이후의 파일들도 같은 매커니즘으로 파일이 저장되는 할당 방식이다.
연속 할당 시스템에서 특정 파일을 읽기 위해 해당 파일의 위치를 식별하기 위해선 파일의 첫 번째 블록 주소와 블록 단위 길이를 활용하면 된다. (첫 번째 블록 주소로 부터 블록 단위 길이 만큼이 해당 파일의 데이터 블록이기 때문)
그래서 연속 할당 시스템의 디렉터리 엔트리는 파일 이름과 첫 번재 블록주소, 블록 단위 길이가 명시된다.
연속 할당 시스템을 오늘 날엔 많이 사용하지 않는데 그 이유는 외부 단편화를 야기할 수 있기 때문이다.
외부 단편화란 연속 할당 시스템에서 파일 a, b, c, d, e 를 저장하고, b 와 d 파일을 삭제 했을 때, 이 두 파일이 있던 공간에는 b 와 d 의 크기 만큼의 파일만 저장할 수 있어 이보다 큰 파일이 들어올 경우 해당 저장 공간들을 사용할 수 없는 문제를 일컫는다.
불연속 할당 - 연속적으로 할당함으로써 발생한 외부단편화를 불연속적으로 저장함으로써 해결할 수 있는데 이를 불연속 할당이라고 한다.
불연속 할당 방법에는 크게 연결 할당과 색인 할당 방법이 있다.
>> 연결 할당 - 파일의 각 블록들이 다음 블록의 주소를 가라키는 형태로, 파일을 이루는 데이터 블록을 연결 리스트로 관리하게 된다. 각 블록들이 다음 블록의 주소의 정보를 가지고 있기 때문에, 블록들이 저장 장치에 흩어져 있어도 읽어들임에 문제가 없다.
연결 할당 시스템의 디렉터리 엔트리에는 파일 이름과 첫 번째 블록 주소, 블록 단위 길이(또는 마지막 블록 주소)를 명시한다.
해당 파일의 첫 번째 블록 주소 부터 블록 단위 길이 만큼 블록들의 다음 블록 주소를 읽어가며, 마지막 블록에선 끝을 알리는 표시자를 확인하게 된다.
연결 할당 또한 단점이 존재하는데 하나는 파일을 읽고 싶을 땐 반드시 첫 번째 블록부터 하나씩 읽어 들여야한다는 점이다. 이는 파일의 중간 부분이나 마지막 부분을 읽어 들이고자 할 때도 처음 블록 주소가 있어야만 찾아 갈 수 있는 연결 할당 방식에 의해 발생된 문제로 파일의 임의 블록 접근시 소요되는 시간이 해당 블록이 첫 블록과의 길이 차이만큼 소요되는 단점이다.
단점 중 다른 하나는 파일 블록들을 읽어가다 한 블록에서 오류가 발생하면 이후 블록들은 접글할 수 없다는 점이 있다.
>> 색인 할당 - 파일의 모든 블록 주소를 색인(index) 블록이라는 하나의 블록에 모아 관리하는 방식으로 파일 내 임의 블록에 접근하기가 용이하다. (연속 할당과 연결 할당의 블록들은 해당 파일의 데이터 블록들로 이뤄져 있다면, 색인 할당은 데이터 블록 + 색인 블록의 구조로 이뤄져 있다고 보면된다.)
색인 할당 시스템의 디렉터리 엔트리에는 파일 이름과 색인 블록 주소를 명시한다.
[FAT (File Allocation Table) 시스템]
- 파일 시스템 중 불역속 할당의 연결 할당 방식을 보완한 방식으로 파일의 각 블록의 주소를 한 곳에 모아서 테이블 형태(FAT)로 관리하는 방식으로 연결 할당에서 임의의 블록 접근시 지연되는 시간을 해결한 방식이다. FAT를 통해 임의의 블록 주소에 바로 접근할 수 있게 되었고, 여기에 더 나아가 FAT 시스템에선 FAT가 메모리에 캐시될 수가 있어 보조기억장치가 아닌 메모리를 통해 바로 접근이 가능해 임의 접근 속도 개선이 한 층 더 개선 되었다.
FAT는 과거 MS 사의 MS-DoS 에서 사용되어 현재의 USB나 SD 카드에서도 자주 사용되는 파일 시스템으로 FAT12, FAT16, FAT32 의 버전등이 있으며, 각 버전의 숫자들은 블록을 표현하는 비트 수를 의미한다.
FAT 파일 시스템으로 저장 장치를 포매팅하면 다음과 같이 파티셔닝되어 포매팅 된다.
예약 영역 | FAT 영역 | 루트 디렉토리 영역 | 데이터 영역 |
FAT 파일 시스템의 디렉터리 엔트리에는 파일 이름, 확장자, 속성(RWX 권한 및 파일과 디렉토리 구분), 예약 영역, 생성 시간, 마지막 접근 시간, 마지막 수정 시간, 시작블록, 파일 크기 등이 명시된다.
FAT 파일 시스템을 통해 파일을 읽어 가는 과정을 보면은
a.sh 파일을 읽기 위해
root 디렉토리 -> 3번의 home 디렉토리의 첫 번째 블록 주소를 읽음
home 디렉토리 -> 15번의 minchul 디렉터리의 첫 번째 블록 주소를 읽음
minchul 디렉토리 -> 9번의 a.sh 의 파일의 첫 번째 블록 주소를 읽음
a.sh 파일 첫 번째 블록 주소를 통해 FAT 에서 이어서 읽어나가면 된다.
(9 -> 8 -> 11 -> 13)
총 경로를 보면 0 -> 3 -> 15 -> 9 -> 8 -> 11 -> 13 순이다.
(FAT 를 자세히 보면 루트를 의미하는 0번과, 디렉토리로 지정된 3번, 4번, 5번, 10번, 15번은 -1 로 처리되어 있는 것도 확인할 수 있다.)
[UNIX 파일 시스템]
- 색인 할당 기반 시스템으로 색인 블록을 i-node(index node) 로 취급을 한다. 이 i-node 는 파일의 속성 정보와 15개의 블록 주소를 저장할 수 있다. i-node 만 읽어도 파일의 속성과 저장 위치를 확일 할 수 있다. UNIX 파일 시스템에선 파일마다 i-node 를 가지고 있으며, 이 i-node 마다 고유의 번호를 가지고 있다.
15 개의 블록주소만 저장한다면 15개보다 큰 파일은 어떻게 관리될까?
이 문제를 해결하기 위해 UNIX 파일 시스템에선 직접 블록 주소 저장과 간접 블록 주소 저장이란 방식을 사용한다.
직접 블록 주소 저장 - 블록 주소 중 처음부터 12개에는 직접 블록(파일 데이터가 저장된 블록)으로 저장한다.
단인 간접 블록 주소 저장 - 13번 째 주소엔 단일 간접 블록(파일 데이터를 저장한 블록 주소가 저장된 블록)으로 저장한다.
이중 간접 블록 주소 저장 - 14번 째 주소엔 이중 간접 블록(단일 간접 블록의 주소들이 저장된 블록)으로 저장한다.
삼중 간접 블록 주조 저장 - 15번 째 주소엔 삼중 간접 블록(이중 간접 블록의 주소들이 저장된 블록)으로 저장한다.
UNIX i-node 파일 시스템의 파티셔닝은 다음과 같이 되어있다
예약 영역 | i-node 영역 | 데이터 영역 |
그럼 이번엔 UNIX 파일 시스템을 통해 파일을 읽어 가는 과정 보자
i-node 영역에서 2번을 통해 1번 블록의 루트 디렉토리를 읽음 (루트 디렉토리는 2번이 고정)
root 디렉토리 -> home 디렉토리의 i-node 를 찾음(3번 i-node)
i-node 영역 -> 3번을 통해 210번 블록의 home 디렉토리를 읽음
home 디렉토리 -> minchul 디렉토리의 i-node 를 찾음 (8번 i-node)
i-node 영역 -> 8번을 통해 121 번 블록의 minchul 디렉토리를 읽음
minchul 디렉토리 -> a.sh 의 i-node 를 찾음 (9번 i-node)
i-node 영역 -> 9번을 통해 98, 12, 13 번 블록을 통해 a.sh 파일 데이터를 읽어감