Directory Entry
이제 파일 시스템의 예시로 UNIX V7 의 파일 시스템이 어떻게 구현되어 있는지 살펴보면서 파일 관련 내용 정리를 마무리한다.
UNIX V7 에서는 위와 같은 형태의 Directory Entry를 가진다.
2바이트(=16 bit)는 I-Node 번호를 표현하는데 쓰이므로 총 2^16 가지의 번호를 표현할 수 있다.
따라서 이 시스템에서 저장할 수 있는 최대 파일의 개수는 2^16개이다. (★)
뒤의 14바이트는 파일 이름을 나타내는데 사용되었다.
I-node
이번에는 UNIX V7에서 사용한 하나의 i-node의 구조를 살펴보자. (★)
i-node 에는 파일의 속성이 들어있고, 그 밑에는 실제 파일의 content가 저장된 디스크 블록을 가리키는 주소가 들어있다.
이때 V7 에서는 10개의 디스크 블록 주소를 가리키는 칸이 있고, 그 밑에는 Single Indirect Block 을 가리키는 주소가,
그 밑에는 Double Indirect Block 을 가리키는 주소가, 마지막에는 Triple Indirect Block을 가리키는 주소가 존재한다.
디스크 블록 하나의 크기가 1KB 이고, 디스크 블록의 주소는 4byte 크기라고 해보자.
Attribute 밑에서부터 존재하는 Disk address 는 위에서부터 차례대로 첫번째 블록의 주소, 두번째 블록의 주소, ... , 10번째 블록의 주소를 가리킨다.
따라서 이 10개의 디스크 블록 주소를 사용하면 이 파일은 총 10KB의 내용을 저장할 수 있다.
하지만 하나의 파일 크기는 10KB보다 더 커질 수 있다.
이 경우에는 그 밑에 있는 주소를 사용한다.
먼저 Single Indirect Block 은 디스크 블록의 주소를 저장하고 있는 디스크 블록이다.
그리고 10번째 블록의 주소 밑에는 Single Indirect Block 의 주소를 저장하고 있다.
Single Indirect Block을 이용하면 하나의 주소가 4byte 이고, 디스크 블록의 크기가 1KB 이므로
1KB / 4byte = 2^10 byte / 2^2 byte = 2^8 개의 디스크 블록 주소를 저장할 수 있다.
따라서 Single Indirect Block을 통해 저장할 수 있는 content 크기는 2^8 KB = 256KB 이다.
만약 여기까지 사용했는데도 공간이 모자라다면, 그 밑에 있는 주소를 사용한다.
이 주소는 Double Indirect Block 을 가리키며, 이름 그대로 2번을 거쳐야 실제 디스크 블록의 주소를 알 수 있는 블록이다.
그러면 Double Indirect Block 에는 동일하게 2^8개의 Single Indirect Block 주소가 들어갈 수 있고,
각각의 Single Indirect Block은 256KB 크기의 데이터를 가리키므로 최종적으로는 2^8 * 2^8 = 2^16 KB = 64000KB 크기의 데이터를 저장할 수 있다.
만약 여기까지도 공간이 모자라다면 마지막으로 그 밑에 있는 주소를 사용할 수 있으며,
이 주소는 Tripple Indirect Block 주소를 가리킨다. 이 블록으로는 같은 방법으로 2^8 * 2^8 * 2^8 개의 디스크 블록을 가리킬 수 있으므로 2^24 KB 의 데이터를 저장할 수 있다.
따라서 이를 다 더하면 하나의 i-node로 표현하는 파일은 4GB + 64MB + 256KB + 10KB 의 데이터를 저장할 수 있다.
File Open
이번에는 /usr/ast/mbox 라는 경로에 있는 파일을 Open 할 때, UNIX 시스템이 어떤 과정으로 파일을 찾아서 여는지 그 과정을 살펴보자.
Open 시스템 콜은 해당 파일의 i-node를 메모리로 로딩하는 것이 목표이므로, i-node 번호를 찾아야 한다.
먼저 위와 같이 절대 경로로 작성했다면, 루트 디렉토리의 i-node는 메모리에 올라와 있다고 가정하자.
그러면 i-node에 저장된 '디스크 블록 주소'를 보면서 root directory의 content를 디스크로부터 가져올 것이다.
위 그림의 맨 왼쪽은 그렇게 가져온 루트 디렉토리(/) 엔트리를 나타낸다.
처음과 두 번째 루트 디렉토리 엔트리는 현재 파일의 i-node와 부모 디렉토리의 i-node 번호를 갖고 있다.
물론 root directory는 부모 디렉토리가 없으므로 같은 값을 갖고 있는 것을 알 수 있다.
현재 목표는 /usr/ast/mbox 파일을 여는 것이 목표이므로,
운영체제는 먼저 루트 디렉토리 내에 usr 라는 디렉토리가 있는지 찾는다.
usr 디렉토리가 존재하고, 해당 파일의 i-node 번호가 6번이므로, 하드디스크에서 6번 아이노드를 메모리로 불러온 뒤, /usr 디렉토리 파일의 디스크 블록 주소 132를 확인한 뒤, 132 디스크 블록을 메모리에 로딩하여 파일 내용을 불러온다.
위 그림의 3번째는 그렇게 가져온 /usr 디렉토리 엔트리들을 보여준다.
다시 여기에서 ast 디렉토리 파일을 찾고, 해당 아이노드 번호 26을 디스크에서 불러오고, 아이노드에 저장된 디스크 블록 주소 406을 메모리에 불러와서 내용물을 읽으면 mbox 파일의 아이노드 번호가 60 이라는 것을 최종적으로 알아낼 수 있다.
이제 Open 시스템 콜은 이 60번 아이노드에 저장된 디스크 블록 주소를 보고 파일에 접근해서 데이터를 읽어오면 정상적으로 파일을 열어서 데이터를 읽고 쓸 수 있게 된다.
이때까지 총 디스크 블록의 로딩 횟수를 세보면 (★)
루트 디렉토리는 이미 올라와있다고 가정하므로 무시하고
usr 디렉토리의 i-node를 가져오는 것 1번
usr 디렉토리의 실제 디스크 블록을 가져오는 것 1번
ast 디렉토리의 i-node를 가져오는 것 1번
ast 디렉토리의 실제 디스크 블록을 가져오는 것 1번
mbox 파일의 i-node를 가져오는 것 1번
mbox 파이르이 실제 디스크 블록을 가져오는 것 1번
총 6번의 디스크 블록 로딩이 발생한다.
만약 루트 디렉토리가 올라와있지 않았다고 가정하면, 루트 디렉토리를 포함하여 7번의 디스크 블록 로딩이 발생할 것이다.
Disk & I-node 구조
위 그림은 UNIX 시스템의 클래식한 디스크 구조를 보여준다.
전에 정리한 디스크 구조에서 하나의 파티션에는 하나의 파일 시스템이 있고,
파일 시스템은 위와 같은 구조로 되어있다고 정리했었다.
data block 들에는 실제 데이터가 들어있는데, 이 내용은 파일의 내용일 수도, 디스크 블록의 주소를 담고 있을 수도 있다.
위 구조는 UNIX V5 의 아이노드 구조를 보여준다.
여기에서 Address 필드의 크기가 39 바이트인데, 10개의 디스크 블록 주소와 3개의 indirect block 주소를 저장해서 총 13개의 디스크 블록 주소를 저장한다는 것으로부터, 디스크 블록 주소 1개의 길이가 3byte 임을 유추할 수 있다.
Gen 필드는 Generation Number 를 말한다.
파일을 만들었다가 지우면 해당 아이노드를 가리키는 link 가 없어지므로 반환되는데, 다시 파일을 만들면 이 아이노드가 재사용될 수 있다.
그때 Gen 필드의 값이 1 증가한다.
Nlinks 필드는 하드링크를 걸 때마다 증가하고, 삭제할 때마다 감소하는 링크 카운트를 저장하는 필드이다.
위 그림은 지금까지 정리한 파일 시스템을 종합적으로 정리해서 보여주는 그림이다.
Open 시스템 콜을 통해 파일을 열면, 아이노드는 디스크의 i-node 테이블에 저장되어 있다가, 커널에 있는 in-memory i-node 테이블의 하나의 엔트리로 아이노드 정보가 로딩된다.
(이때 이 테이블 엔트리의 개수는 전에 정리한 것처럼 파일 시스템에서 정한 최대 열 수 있는 파일의 개수만큼이 될 것이다.)
Open 시스템 콜을 호출한 '프로세스' 내부에 있는 File Descriptor Table의 엔트리 하나는 커널에 있는 Open File Description의 한 엔트리를 가리킨다. 그리고 Open 시스템 콜은 이 Open File Description 엔트리 '인덱스'를 반환한다.
이 엔트리는 i-node를 가리키는 동시에, File position (현재 파일의 어느 부분을 읽고/쓰고 있는지) 등의 정보를 추가적으로 저장하고 있다.
이를 통해 파일에 접근해서 읽고 쓰기를 진행할 수 있게 된다.
다른 프로세스가 동일한 파일에 접근하는 경우, 해당 프로세스 내부의 file descriptor table 은 같은 i-node를 가리키는 또 다른 Open file description의 엔트리를 가리킨다.
이 엔트리는 기존 프로세스와 별개의 엔트리 이므로 file posititon 이 독립적으로 존재한다.
반면 부모 프로세스가 자식 프로세스를 생성하는 경우, 부모 프로세스의 내용을 모두 복사해서 생성하기 때문에 같은 open file description 엔트리를 가리키게 되며, 부모가 파일 포지션을 바꾸는 경우, 자식 프로세스에서도 변경된 파일 포지션을 확인하게 된다.
(이런 특징은 쉘 프로세스에서 사용한다고 한다.)
정리하면 위 그림에서 왼쪽은 프로세스, 가운데는 커널, 오른쪽의 i-node 정보 역시 커널에 있는 i-node 테이블에 저장이 되고,
file position 정보는 커널에 있는 Open File Description 엔트리에 저장된다. (★)
(i-node 또는 file descriptor table이 아니다.)
'CS > 운영체제' 카테고리의 다른 글
[운영체제] 22. Disk & RAID (0) | 2024.12.10 |
---|---|
[운영체제] 21. I/O Device (0) | 2024.12.09 |
[운영체제] 19. 파일 시스템 구현 (0) | 2024.12.08 |
[운영체제] 18. File & Directory (0) | 2024.12.07 |
[운영체제] 17. Segmentation (0) | 2024.12.05 |