BASIC의 개발 노트
File System 본문
File System에는 File과 Directory가 존재한다.
File을 먼저 간단하게 살펴볼텐데, Process의 구조를 보면 주소 공간 메모리를 추상화한 Address Space와
PCB(Process Control Block)가 존재하고 Process 마다 File Descripter Table을 하나씩 가지고 있다.

File Descripter Table에서 처음 3칸은 미리 할당을 해놓는다. Standard I/O를 위해서 할당해놓는 것인데
stdin, stdout, stderr는 각각 대표적으로 키보드, 모니터를 말하고 stderr는 에러를 출력하기 위해서 구별해서 쓴다.
만약 File을 Open하게 되면 0, 1, 2 다음 숫자가 3번이기 때문에 3번 슬롯에 File 정보를 넣어주게 된다.
다른 Process에도 3번이 존재하는데, 만약 프로세스 0과 1이 있을 때 이들은 서로의 존재를 모른다.
이는 프로세스가 서로 격리 되어있기 때문이다.
따라서 프로세스 별로 갖는 File Descripter Table의 번호가 같은 것은 전혀 문제가 되지 않는다.
File의 이름을 바라보는 관점이 System과 사용자(사람)가 각각 다른데
System 내부에서의 이름은 File Descripter Number가 되고, 사람이 볼 때의 이름은 경로(PATH)가 된다.
#include <stdio.h>
#include <unistd.h>
#include <assert.h>
#include <fcnt1.h>
#include <sys/types.h>
int main(int argc, char *argv[]){
int fd = open("/tmp/file", O_WRONLY|O_CREAT|O_TRUNC, S_IRWXU);
assert(fd > -1);
int rc = write(fd, "hello world\n", 13);
assert(rc == 13);
close(fd)
return 0;
}
그래서 이를 Code에서 보면 open이라는 것은 사람의 관점에서 본 이름을 System 관점에서,
특히 프로세스 관점에서의 이름으로 전환해준다.
앞에서 프로세스 별로 File Descripter Table을 갖는다고 했는데,
System 차원에서 바라볼 때 Kernel Level에 Open File Table과 i-node Table이 존재한다.
Open File Table
앞에서 말한 File Descripter Table의 3번 슬롯이 Kernel Level에서 실질적으로 관리가 되는 곳.
주로 offset이나 실제 물리적으로 File이 어디에 위치해있는지를 가리키고 있다.
i-node Table
사람이 볼 때는 경로, 프로세스가 볼 때는 File Descripter 라고 했는데,
Open File Table을 통해서 File Descripter가 i-node라는 것으로 변환이 된다.
우리의 실제 하드디스크 판에서는 i-node를 가지고 식별을 하고 실제 물리 Level에서 File의 이름은
i-node number가 된다. (i-number 라고도 부른다.)
따라서 File 이름은 궁극적으로는 i-number 까지 내려와야한다.
정리하면 물리적으로는 i-number, 프로세스 안에서는 File Descripter, 사람이 볼 때는 경로가 된다.
File System은 결국 하드디스크에 File의 내용, 이름, 정보(Meta Data), File 자체 등 이런 것들을 어떻게 구성을 해서
HDD나 SSD에 어떻게 쓸 것인가에 대해 결정하는 것을 다룬다.
그래서 이런 방식으로 저장되는 File이라는 것은 관점에 따라 정의가 조금씩 달라지지만
사용자 입장에서는 Durable Data Structure로 본다.
메모리에 있는 자료구조는 전원 공급을 끊으면 사라지기 때문에 File로 쓰거나 읽어와야한다. -> Durable (지속적)
여기서 File을 읽거나 쓰거나 할 때 등장하는 것이 System Call(Write, Close 등) 이며
이 Level에서의 File은 Bytes의 Collection, 즉 바이트들이 모여 있는 것으로 여긴다.
또 다른 관점이 있는데 바로 System's view inside OS, 즉 하드 디스크까지 내려갔을 때 File을 어떻게 볼 것이냐 인데
이 때는 block들을 모아놓은 것으로 본다. block은 logical transfer unit인데, 하드 디스크에서 메모리로 이동을 할 때
이를테면 읽거나 쓰기 등의 작업에서의 단위를 block 이라고 한다.
또한 block 안에 보면 더 작은 단위의 데이터 전송 등이 이루어지는 부분이 있는데, 이를 sector 라고 한다.
sector는 일반적으로 512 Byte, Block은 여러 개의 sector로 block을 구성하고 있으며
운영체제 마다 그 크기가 다르겠지만 UNIX나 LINUX의 경우 4KB 정도 사용한다.
이 sector 라는 것이 가지는 의미는 굉장히 중요하다.
메모리에서 하드 디스크로 전송(읽기/쓰기)이 이루어질 때 sector 단위로는 atomic 하게 읽거나 써진다.
어떤 내용을 쓰는데 하나도 안썼거나 sector를 제대로 다 썼거나 둘 중 하나라는 뜻이다.
여기까지 정리하면 똑같은 File 이라는 것을 볼 때 세 가지 관점으로 나누어서 볼 수 있다.
1. 사용자가 볼 때
2. System Call Level 에서 볼 때
3. 실제 물리적 Level에서 볼 때
File의 실제 데이터 자체는 Block들을 모아서 읽고 쓰는데 (논리적으로 읽고 쓸 때는 Block 단위이기 때문이다.)
File에는 소유자, 읽고 쓸 수 있는 사용자에 대한 정보, 만들어진 날짜, 마지막 수정 날짜 등의 메타 데이터가 존재한다.
따라서 이런 메타 데이터를 저장할 곳이 필요한데, 이를 Head 라는 것을 따로 만들어서 저장한다.
Head에 저장하는 것은 Block 만큼 크지 않아도 되며 한 Block안에 여러 개의 메타 정보를 넣을 수 있다.
이를 UNIX/LINUX에서는 i-node 라고 이름을 붙였다.
그래서 물리적 Level까지 가면 이 i-node라는 Head(메타 정보를 저장한 곳)를 살펴보면
어떤 Block을 쓰고 있는지를 나타내고 있고 이 정보는 i-node Table에 들어가있다.
하지만 i-node Table은 영속성을 가져야하기 때문에 그 정보는 하드 디스크에도 써진다.
(이렇게 하드디스크에 써진 i-node Table이 메모리로 추상화 되서 올라가는 것이다.)
File을 간단하게 살펴보았으니 이제 File System에 다른 부분, Directory를 살펴보자.
앞에서 경로에 대한 얘기가 나와서 Directory에 대한 예상은 어느정도 되는 상황이다.
Directory는 계층 구조를 이루고 있고 이에 따라 절대 경로, 상대 경로가 존재할 수 있다.
절대 경로는 루트에서 시작하게 되고, 상대 경로는 임의의 위치에서 시작한다고 보면 된다.
여기서 경로라는 것은 유니크 하다.
하지만 이것은 Directory가 갖는 특성이고 그래서 Directory가 무엇이냐 라고 한다면
사람이 아는 String과 System이 아는 고유의 숫자의 Pair로 구성된 것이다.
여기서 말하는 고유의 숫자는 i-node number를 말한다. 즉 i-node Table에서의 index 값을 의미한다.
이는 System 차원에서 유니크하게 하나씩만 존재한다.
따라서 Directory는 <file name, i-node number> mapping 이라고 볼 수 있다.

my 자신은 200이 되고 my의 위에는 2가 있다.
book 기준으로 보면 자신은 100이고 book 위에는 200이 있다.
이런 정보들을 가지고 종합해보면 계층 구조를 가지고 있다는 것을 알 수 있다.
중요한 것은 이러한 정보를 어떻게 구성을 해서 어떻게 하드디스크에 쓸 것이냐이다.
-> File의 구조대로 해도 가능하다. 즉 물리적인 모양이 같다. (구별도 하지 않는다.)
Directory에도 데이터가 존재하고, 데이터에 대한 메타 정보가 존재하기 때문에 Head, Block 모두 File과 같이 사용한다.
장치들의 이름 역시 File 처럼 추상화를 했기 때문에 장치를 Open, Read, Write, Close 를 한다.
그러기 위해선 이름을 가져야하는데 경로를 따라 갈 수 있는 이름을 부여한다.
장치를 나타내는 File은 Block 들이 필요없다. 장치에서는 데이터가 따로 있는 것이 아니기 때문이다.
따라서 Device를 위한 Head의 정보는 이 장치에 쓰기 위해선 kernel의 어떤 함수를 호출해야한다 하는 정보가 담겼다.
즉 함수를 mapping 하는 Table이 존재한다. (device driver mapping table)
또한 kernel 안에 pipe, socket 등의 구조가 있는데, interface를 보면 File처럼 Read, Write를 한다.
따라서 경로를 가져야하고 그러다보니 하드디스크에서는 물리적으로 File 처럼 보인다.
마찬가지로 데이터 Block은 필요없고 Head만 필요하다.
정리하면 File, Directory의 경우 Head와 데이터를 담는 Block이 같이 있고,
장치, Pipe, Socket 등은 Head만 있으면 된다.
여기까지가 File System에 대한 전체적인 그림이었다.
'OS' 카테고리의 다른 글
| Concurrency (0) | 2021.06.04 |
|---|---|
| File System - Read & Write + Directory (0) | 2021.05.26 |
| RW Lock - Bad Case & Good Case (0) | 2021.05.24 |
| Semaphore Bounded Buffer Problem (0) | 2021.05.23 |
| Semaphore (0) | 2021.05.22 |