2022. 9. 19. 01:29ㆍ개발 관련 책 읽기/리눅스 커널 내부구조
파일시스템이 관리하는 데이터는 크게 Meta Data / User Data로 구분할 수 있다.
FAT 파일시스템에서 메타데이터는 FAT 테이블,디렉토리 엔트리 그리고 수퍼 블록으로 구성된다.
파일시스템은 각 파일마다 디렉터리 엔트리를 하나씩 갖는다. 이것은 마치 태스크가 하나 생성되면 task_struct라는 구조체를 통해 각 태스크를 관리하는 것과 유사하다. 디렉터리 엔트리가 모여 디렉터리를 구성한다. 리눅스에서는 디렉터리와 파일은 별도 구분 없이 파일로 취급한다.
결국 디렉터리는 자신이 포함하는 파일의 이름들을 데이터로 가지고 있는 특수한 파일에 불과하다.
각 파일시스템은 저마다 자신만의 디렉터리 구조체를 선언해 놓은 뒤,파일이 생성될 때 이 구조체의 각 내용들을 채워서 디스크에 저장한다. 나중에 사용자가 특정 이름을 가지는 파일의 내용을 읽어오도록 파일시스템에 요청한다면, 파일시스템은 사용자가 요청한 파일의 이름을 가지고 디렉터리 엔트리를 찾아낸 뒤 ,디렉터리 엔트리가 가지고 있는 정보를 통해 데이터 블록을 찾아서 사용자에게 제공해 주는 것이다.
슈퍼블록은 파일 시스템의 전체적인 정보와 '/'(root) 디렉터리의 위치를 기억하는것이다.
최상위 디렉터리 엔트리의 위치를 알 수 있으면 '/' 디렉터리 하위에 존재하는 다른 모든 파일을 찾을 수 있게 된다.
i-node
리눅스의 디폴트 파일시스템인 ext4등의 ext계열 파일시스템이 채택하고 있는 inode에 대해서 알아보자.
i_blocks 필드는 이 파일이 몇 개의 데이터 블록을 가지고 있는지 나타내며, i_mode는 이 inode가 관리하는 파일의 속성 및 접근 제어 정보를 유지한다. i_links_count는 이 inode를 가리키노 있는 파일 수를(또는 링크 수를)의미하며, i_uid와i_gid는 파일을 생성한 소유자의 user ID와group ID를 의미한다.
i_atime,i_ctime,i-mtime은 각각 파일의 접근 시간,생성 시간,수정시간을 의미한다.
i_mode는 16비트로 구성되며,이중 상위 4개의 비트는 파일의 유형을 의미한다. 파일의 유형에는 정규파일(S_IFREG), 디렉터리(S_IFDIR), 문자 장치 파일(S_IFCHR), 블록 장치 파일(S_IFBLK),링크 파일(S_IFLNK), 파이프(S_IFFIFO), 그리고 소켓(S_IFSOCK)등이 있다.
그 다음에 위치한 3개의 비트는 특별한 목적으로 사용된다. u bit는 setuid 비트로, 파일이 수행될 때 수행시킨 태스크의 소유자 권한이 아닌, 파일을 생성한 사용자의 권한으로 동작할 수 있도록 한다.
g비트는 setgid비트이다. s는 sticky비트로 태스크가 메모리에서 해제될 때,swap공간에 유지되도록 할 때, 또는 디렉터리에 대한 접근 제어에 사용된다.
그 다음의 9개 비트는 파일의 접근 제어(R/W/E)에 사용된다.처음 3개는 사용자에 대한 접근, 그 다음 3개는 그룹에 대한, 마지막 3개는 다른 사용자들에게 대한 접근 제어에 사용된다.
inode 하단부에는 i_block[15]필드가 존재하는데, 이것은 파일에 속한 디스크 블록 들의 위치를 관리하기 위해 사용된다. i_block[15]은 총 15개의 엔트리가 존재하는데, 이중 12개는 직접 블록(Direct block)이고 3개는 간접 블록(indirect block)이다. 직접 블록은 실제 파일의 내용을 담고 있는 디스크의 데이터 블록을 가리키는 포인터이다(block *p). 반면 간접 블록은 인덱스 블록(디스크 블록을 가리키는 포인터들을 갖는 블록)을 가리키는 포인터이다. 더블 포인터라고 생각하면 이해하기 쉬울것이다(block **p)
3개의 간접 블록은 다시 단일 간접 블록,이중 간접 블록 ,삼중 간접 블록으로 구분된다. 단일 간접 블록은 1개 ,이중은 2 단계 , 삼중은 3단계의 인덱스 블록을 가진다. 이러한 Ext계열 파일시스템의 inode구조에서 지원할 수 있는 파일의 최대 크기는 얼마일까? 디스크 블록의 크기가 4KB라고 가정하면,
직접 블록으로 지원할 수 있는 파일의 크기는 48KB(12*4KB)이다. 간접 블록들은 인덱스 블록을 갖는다. 인덱스 브록도 결국 디스크 블록에 존재하며 따라서 인덱스 블록의 크기는 4KB이다. 인덱스 블록은 디스크 블록을 가리키는 포인터들로 구성되므로,각 포인터를 위해 4byte(32bit 기준)가 필요하다.
따라서 하나의 인덱스 블록에는 1024개의(4KB/4byte) 포인터가 존재하게 된다.단일 간접 블록으로 지원할 수 있는 최대 크기는 1024*4KB 이므로 4MB가 된다.이중 간접 블록은1024*1024*4KB 4GB
삼중 간접 블록은 1024*1024*1024*4KB 4TB만큼을 지원할 수 있다.
결국 디스크 블록의 크기가 4KB이고 인덱스의 각 포인터(엔트리) 크기가 4byte인 시스템 환경에서
inode 구조가 지원할 수 있는 최대 크기는 48KB+4MB+4GB+4TB가 된다. 하나의 파일이 사용하기에는 충분히 큰 공간이다.
inode를 접근하면 파일의 속성 정보들과 파일에 속한 디스크 블록들의 위치를 파알할 수 있음을 알수있다. 그럼 파일의 이름과 inode는 어떻게 연결될까?이때 이용되는 것이 디렉터리 엔트리이다.
아래는 ext2 파일시스템의 디렉터리 엔트리이다.
#define EXT2_NAME_LEN 255
struct ext2_dir_entry{
_le32 node; /* Inode number */
_le 16 rec_len; /* Directory entry length */
_le 16 name_len; /* Name length */
char name[]; /* File name */
Ext2 파일시스템은 모든 파일에게 고유한 inode 번호를 부여한다.(ext3도 동일). 이 번호는 파일시스템이 관리하는 공간의 앞부분에 위치하고있는 inode의 테이블에서의 번호를 의미한다.
Ext2 파일시스템의 디렉터리 엔트리는 이름과 inode번호 같은 간단한 정보만을 유지하며, 실제 데이터 블록 인덱싱과 같은 세부적인 정보는 inode 번호를 가지고 찾을 수 있는 inode 자료구조에 유지된다.
EXT2 파일시스템
Ext2 파일시스템의 세부적인 구조에 대해 알아보면서 동작 원리를 이해해 보도록 하자.
Ext2 파일시스템을 기반으로, 다양한 형태의 겨함에 강인한 저널링 기능을 추가한 것이 Ext3와 Ext4 파일시스템이다. 따라서 Ext3와 Ext4는 디스크에 실제 저장하는 대부분의 내용이 Ext2와 호환된다.
Ext2 파일시스템은 디스크의 성능을 높이기 위해 서로 관련된 inode와 디스크 블록들을 인접한 실린더에 유지하려고 한다. 즉 같은 파일에 대한 inode와 디스크 블록들을 인접한 실린더에 유지하여 디스크의 탐색 시간을 줄이려 하는 것이다. 이를 위해 Ext2는 인접한 실런더를 블록그룹으로 정의하였다.
수퍼 블록과 그룹 디스크립터는 소실되면 안 되는 매우 중요한 정보이기 때문에 각 블록 그룹마다 중복하여 기록하고 있다. 따라서 한 그룹에 있는 수퍼 블록이나 그룹 디스크립터의 내용 전체 또는 일부가 소실되었다 하더라도 다른 그룹에 존재하는 내용을 기반으로 복구가 가능하다(e2fsck 같은 유틸리티의 동작 원리이다)또한 파티션에 ext2파일시스템을 구축하고 나서 마운트하며 자동으로 생성되어 있는 lost+found라는 파일은 정상적으로 연결되어 있지 않는 디렉터리 엔트리를 넣어 두는 창고 역할을 한다.
'개발 관련 책 읽기 > 리눅스 커널 내부구조' 카테고리의 다른 글
Chapter 6 - Interrupt/Trap & System call(1) (0) | 2022.09.19 |
---|---|
Chapter 5 - 파일 시스템(3) (0) | 2022.09.19 |
Chapter 5 - 파일 시스템(1) (1) | 2022.09.19 |
Chapter 4 - 메모리 관리(3) (1) | 2022.09.19 |
Chapter 4 - 메모리 관리 (2) (0) | 2022.09.19 |