휴...일단 여기 부분은 매우매우 중요하고, 내용도 어렵고, 분량도 많아서 집중해야 합니다!
자 가봅시다!
이번 시간에는 UNIX/ RINUX 운영체제의 File System의 사례에 대해 알아봅시다!
1. UNIX File Management
1-1. 파일의 유형들
Regular file(ordinary file) : 일반파일
Directory : 디렉토리
Special file : 특수파일 (ex) Named pipes, Links, Symbolic links)
1-2. UNIX File System
boot block, super block, inode list(=inode table=FCB list), data blocks(File 내용저장)으로 이루어져있습니다.
(참고: https://coding567.tistory.com/81)

먼저 FCB를 복습해볼까요?
FCB는 파일에 대한 정보(속성)을 지닌 커널 데이터 구조로 각 파일 당 한 개씩 가집니다.
FCB안에는 file name, file size(bytes), user_id, group_id, file operation, creation time, last modified, last access time, addresss of file data 등이 저장됩니다.
또한 FCB 1개는 128byte입니다.
(참고: https://coding567.tistory.com/79)
2. Inodes
- UNIX의 FCB를 Index node라고 합니다.
- 특정 파일에 대한 주요 정보를 포함하는 제어 구조입니다.
* UNIX Disk-Resident inode 속 정보
1. File Mode : 파일과 관련된 파일 유형, 접근 권한 및 실행 권한을 저장하는 16비트 플래그입니다.
2. Link Count : 이 inode에 대한 디렉터리 참조 횟수(=몇 개의 디렉토리에서 이 파일을 가리키는지)
3. Owner ID : 파일의 개별 소유자
4. Group ID : 이 파일과 관련된 그룹 소유자
5. File Size : 파일의 바이트 수
6. File Addresses : 39바이트의 주소 정보
7. Last Accessed : 마지막 파일 엑세스 시간
8. Last Modified : 마지막 파일 수정 시간
9. Inode Modified : 마지막 inode 수정 시간
디렉토리 chapter에서 dangling pointer를 해결하는 방법으로 entry count방법을 사용했는데,
link-count가 0이면, 파일 그 자체를 지우게 되며, 0이 아닐 경우, 다른 링크가 존재한다는 것이므로 파일을 그대로 둡니다.
이때, 파일을 지울 때, inode를 같이 지우게 됩니다.
(참고: https://coding567.tistory.com/80)
3. Data Blocks의 Addresse들
앞서 배운 파일 할당 방법으로는 Contiguous allocation, Linked allocation, Indexed allocation이 있었습니다.
(참고: https://coding567.tistory.com/82)

3-1. UNIX의 파일 할당 방법은 그 중에서 indexed allocation method를 약간 변형해 사용합니다.
UNIX 운영체제에서는 이러한 block number를 가리키는 Index block을 file allocation table에 두는 것이 아니라 각 파일의 FCB(inode)에 저장합니다!!!
이때, index number(block number)를 모두 index block에 저장하는 것이 아니라 일부(첫 10개)는 inode에 저장합니다.
- 10개의 data block numbers는 inode의 direct block 영역에 저장됩니다.
- 더 많은 data block numbers는 data block(index blocks)에 저장됩니다.
- 이 index block의 data block numbers는 3개의 indirect block 영역에 저장됩니다.
3-2. 하나의 인덱스 블록은 일반적으로 데이터 블록의 4096bytes(=4KB)와 같은 크기입니다!
하나의 index block 속 block number의 수 = 인덱스 블록 크기 / 하나의 블록 넘버 크기 = 4096B /4B = 1024개

4. Data Block Addressing!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 중요!

1. 다음 그림과 같이 inode에는 여러 정보들과 10 direct block(UNIX 초기 버전) 과 3 indirect blocks의 내용을 지닙니다.
2. 나중에 10 direct block이 12개로 확장됩니다.
3. 10개의 direct block 각각에는 block number가 저장되어있는데, block number는 4byte이므로, 10개의 direct block의 크기는 40B입니다.
4. 10 direct block의 의미는 직접 data block에 접근하는 블록이 10개라는 의미입니다. 참고로 data block 하나의 크기는 4KB입니다.
5. 3 indirect blocks는 file 공간 부족 시에 추가적으로 할당하는 블록들로 간접적으로 블록에 접근합니다.
6. 3 indirect blocks는 single indirect, double indirect, triple indirect가 있습니다.
7. 아까 배운대로 index block은 1024개의 index number를 저장합니다. 그림을 기억합시다!
8. single indirect는 한 번 index block을 거쳐가는 것이고, double indirect 는 두 번 index block을 거쳐가는 것이고, triple indirect는 세 번 index block을 거쳐가는 것입니다.
9. 그래서 single indirect의 경우, index block의 번호를 저장해 index block을 거쳐가면, index block 안에는 1024개의 index number가 저장되며, 특정 index number로 가면 4KB의 특정 블록으로 이동하게 됩니다.
10. 이때, single indirect가 가리키는 index block은 1024개의 index number를 저장하는데, 이미 10 direct block에 10개의 block number를 저장했기 때문에, index block 안의 block number가 0번인 것은 11번째 블록을 가리키며, block number가 1023번인 것은 1033번째 블록을 가리키게 됩니다. 따라서 single indirect block의 block number들은 11번째~1033번째 블록을 가리킬 수 있습니다.
이제 본격적으로 Maximum Block size를 계산해봅시다.
계산 전 참고사항
* 1KB = 2^10 bytes (=1024bytes=약 1000bytes=1KB)
* 1MB = 1000KB = 2^20 bytes
* 1GB = 1000MB = 2^30 bytes
* 1TB = 1000GB = 2^40 bytes
- Directly accessed: 40KB (10x4x2^10 bytes), 4K bytes per block
- Single indirection: 4MB (4KB x 2^10 = 2^22 bytes)
- Double indirection : 4GB (4KB x 2^10 x 2^10 = 2^32 bytes)
- Triple indirection : 4TB
- Maximum size of a file = 4TB = 4GB + 4MB + 40KB
먼저, Directly accessed의 경우, 한 블록 크기가 4KB인 블록을 가리키는 block number가 10개 있으므로 4KB x 10 = 40KB의 최대 블록 크기를 가집니다. 4B x 2^10 x 10 = 40KB로 구할수도 있습니다. 왜냐하면, 1KB는 1024B이기 때문입니다.
40KB의 최대 블록 크기를 가지는데, 더 공간이 필요해 블록을 늘려야 하면, single indirection을 사용합니다.
Single indirection의 경우, 각각의 블록 크기가 4KB인 블록을 가리키는 index number가 1024개 존재하므로, 4KB x 1024 = 4MB의 최대 크기를 가집니다. 4KB x 2^10 = 4MB로 구할 수도 있습니다. 또한, 4KB x 2^10은 2^2 x 2^10 x 2^10이므로 2^22bytes로도 표현할 수 있습니다.
만약, single indirect까지 사용해 4MB + 40KB크기의 공간을 사용했는데, 더 공간이 필요하면, 한 블록을 추가하기 위해 double indirect를 사용하게 됩니다.
Double indirection의 경우, 각각의 블록 크기가 4KB인 블록을 가리키는 index number가 1024개 존재하며, 이 index block을 가리키는 index block이 또 존재해 index number가 1024개 존재하기 때문에, 4KB x 2^10 x 2^10 = 2^32 bytes = 4GB의 최대 블록 크기를 가집니다.
마찬가지로 Triple indirection의 경우, 4KB x 1K x 1K x 1K = 4TB의 최대 블록 크기를 가집니다.
이때, Triple indirection의 경우, disk접근을 4번 하면, file내용을 읽기가 가능하므로 시간이 많이 걸리는 단점을 가집니다.
따라서 single indirect가 triple indirect보다 시간을 단축시킵니다.
따라서 Maximum size of a file은 4TB + 4GB + 4MB + 40KB입니다. 이떄, 이것을 하나의 단위로 맞춰 더해서 계산할 필요없습니다.
이것보다 더 큰 파일 만드는 것도 기술적으로 가능합니다. block size를 크게 키우거나 indirect block을 더 두면 됩니다.
그래서 요즘에는 16TB까지 지원하기도 한다고 합니다.
하지만 파일 한 개의 크기가 너무 크면 비효율적이므로, 파일 몇 개에 나눠서 저장하는 방법이 효율적입니다. 그러면, 읽기와 쓰기 속도도 더 빨라집니다.

이제부터는 UNIX가 아니라 Linux 운영체제의 File System에 대해 알아봅시다.
5. Linux Virtual File System
리눅스에서 가상 파일 시스템은 실제 파일 시스템이 아니라 논리적 파일 시스템을 말합니다!
- 사용자 프로세스에 대한 통일된 파일 시스템 인터페이스
- 상상할 수 있는 모든 파일 시스템의 일반적인 기능과 동작 나타냄
- 대상 파일 시스템과 관계 없이 기본 속성을 공유하는 객체로 파일을 가정합니다.
File System접근하는 알고리즘은 모두 다른 것이 일반적입니다. 일반 사용자들이 File을 열어서 읽고 처리하고 또 저장하는 응용 프로그램 저장 시에는 내 데이터가 저장되는 File이 어떤 파일 시스템에 있는 파일이냐에 따라 파일 접근 방법이 달라집니다. 예를 들어 File open, read, write시스템 콜이 파일 시스템마다 다르며, 그에 따라 응용 프로그램 구현은 달라져야 합니다. 시스템 콜은 코딩해야 하며, 자주 일어납니다. 또한, 다른 예시로 신주소체계 응용프로그램 구현 시 오래된 주소 데이터는 Windows, DOS OS, NTFS File System으로 저장 가능합니다. 그런데, 현재 사용하는 OS가 다르게 되면, 읽지 못해 프로그램을 짜야 해서 불편하게 됩니다. 원래 OS의 목적은 일반 사람들을 쉽게 편하게 하기 위해서였습니다. 따라서 파일 시스템 종류에 상관없이 리눅스에서 다 접근해서 읽을 수 있게 만든 것이 바로 가상 파일 시스템입니다.

다음 그림은 리눅스 가상 파일 시스템의 개념적 구조입니다.
User Process에서 System call을 받으면, Linux kernel로 가게 됩니다.
Linux Kernel 속에 있는 System calls interface로 와서 virtual File System(VFS)에서 path를 보고 특정 FS로 변환시킵니다. IBM JFS, DOS FS, extFS, ext2FS등이 있습니다. 이런 것들은 모듈 기능이며, 필요하면 동적으로 OS에 추가, 삭제가 가능합니다. 특정 FS에서 Page Cache로 가게 되면, disk cache로 disk block을 임시 저장합니다. 그 후, Device drivers를 거치고, I/O 요청을 받으면 Hardware 속 Disk controller로 이동하게 됩니다.
6. Linux Inode

다음 그림은 ex2파일 시스템에서 데이터 블록의 주소 지정 방법을 나타낸 그림입니다.
이전의 UNIX의 FCB의 inode에는 10개의 direct Blocks가 있었는데, Linux의 inode에는 12개의 direct Blocks이 있습니다.
이러한 파일시스템은 ext2, ext3, ext4파일 시스템이 있으며, ext2,ext3 파일 시스템은 inode의 크기가 128bytes이며, ex4파일 시스템에서 inode의 크기는 2배로 256bytes입니다.
그런데 갑자기 의문이 들 수 있습니다.
분명, 아까 최대 블록 크기를 계산했을 때는 4TB+4GB+4MB+4KB로 엄청 컸는데 왜 inode의 크기는 128bytes밖에 안 되는거지?
그 많은 block 포인터들이 inode에 다 들어간다면, inode의 크기가 엄청 커야 하지 않을까?
그런데, 실제로는 inode의 크기는 일반적으로 128~256바이트 정도에 불과한다고 합니다.
왜냐하면, inode안에는 직접 데이터가 아닌, 몇 개의 포인터(주소)만 들어있어서 파일 자체를 담는 게 아니라, 파일이 어디에 저장되어 있는지를 알려주는 포인터들만을 담는 "지도" 역할을 하기 때문입니다.

따라서, 60바이트 정도만 block 포인터에 사용되고,
나머지는 메타데이터 저장에 사용되어도 전체 inode 크기는 보통 128B 또는 256B 내에 충분히 들어갑니다.
7. Linux File Operations(심화)
앞서서 우리는 파일 연산(파일 동작들)에 대해서 학습했습니다.
파일을 위한 시스템 콜로는
- open, close
- read, write
- lseek
- dup
- link
- pipe, mkfifo
- mkdir, readdir
- mknod
- stat
- mount
- sync, fsck
등이 있습니다.
파일 연산을 하기 위해서는 응용 프로그램이 직접 찾아가서 하는 것이 아니라 시스템 콜 형태로 os에게 요청합니다. 그러면 os는 내가 읽거나 쓰기 원하는 파일이 어떤 파일인지를 os가 판단해서 그 파일 타입에 따라 적절한 파일 연산을 수행합니다.
예를 들어, 보조기억장치 속 일반파일을 read하는 동작과 장치파일을 read하는 방법이 서로 다릅니다.

다음 그림은 리눅스 파일 연산들 그림인데, FCB안에는 file type이 존재하는데, 이 file type(일반파일, 장치파일, 특수파일) 별로 file operations가 달라집니다. 또한, OS의 메모리에 file operation의 함수 주소가 들어있는 table을 저장합니다.
가운데의 file_operations 구조체는 일반적인 함수에 대해 공통적으로 가집니다. 이 구조체 안에는 lseek(), read(), write(), readdir(), poll(), ioctl(), mmap(), open(), flush(), release(), fsync(), fasync() 등이 있는데, 순서대로 저장합니다. lseek()는 lseek함수가 들어있는 메모리의 주소를 저장합니다.
ext2 file system, NFS, pipe, socket, char.device file, block device file등은 추가적으로 연산함수를 추가할 때 사용합니다. ext2 file system의 경우, 8번째 자리가 NULL이므로 추가적인 open이 없다는 뜻입니다. char.device file에서 첫번째가 NULL이므로 lseek() 가 존재하지 않는다는 의미입니다. 8번째 자리가 chrdev_open이므로 open()도 하고 추가적으로 chrdev_open도 해야 한다는 의미입니다.
그래서 이러한 file operation을 FCB안에 저장합니다.


파일을 위한 커널 데이터 구조를 봅시다. 리눅스에서는 task_struct라는 PCB를 사용합니다. task_struct안의 files는 files_struct의 주소를 저장합니다. 그래서 주소를 따라가면, files_struct가 존재하게 되며, files_struct안에는 std_in, std_out, std_err의 파일 3개가 처음의 3개 파일로 저장되게 됩니다. 이후 4번째 이후부터는 파일 디스크립터가 files_struct의 index값을 줘서 이동하면, file table 속, file로 이동하게 되며, FCB와는 다른 정보를 지니게 됩니다. 그 후 file이 FCB의 inode를 가리키게 되고, file의 고유정보가 저장되어있습니다. 이때, fd = open("/usr/member/list.txt".read);와 fd2 = open( "/usr/member/list.txt".RW);는 open용도가 달라서 다른 open이며, 예를 들어, files_struct에서 3번 index가 file을 read하는 것이고, files_struct에서 4번 index가 file을 write하는 것이면, file table 속 file이 다르게 됩니다. 하지만, 같은 inode를 가리킵니다.
따라서 file table 속 file은 dynamic 정보를 저장하며, inode는 static정보를 저장합니다.
task_struct와 files_struct 는 process data structure이므로 프로세스마다 존재하지만,
file table, inode는 kernel 공통 data structure로 모든 프로세스가 공통적으로 가지는 커널 하나에 존재해 각각의 프로세스마다 하나씩 이 구조를 가지지는 않습니다.



'운영체제및실습' 카테고리의 다른 글
| [운영체제및실습] 10주차 3회차 : I/O제어 : 인터럽트 I/O, DMA (0) | 2025.05.12 |
|---|---|
| [운영체제및실습] 10주차 2회차: I/O제어 : 폴링 (0) | 2025.05.10 |
| [운영체제및실습]10주차 1회차: 인터럽트 처리 (0) | 2025.05.10 |
| [운영체제및실습] 9주차 3회차 : 입출력관리 개요 (0) | 2025.05.07 |
| [운영체제및실습] 9주차 1회차: 데이터 블록 관리 (0) | 2025.04.29 |