Linux VFS(Virtual File System Switch) 해부
추상화 및 상위 레벨 개념
요약: Linux®는 유연성과 확장성 그 자체라고 할 수 있습니다. VFS(Virtual File System Switch)를 사용해 보십시오. 기존 디스크와 USB 플래시 드라이브, 메모리, 기타 스토리지 장치와 같은 다양한 장치에서 파일 시스템을 작성할 수 있습니다. 다른 파일 시스템의 컨텍스트 내에 파일 시스템을 삽입할 수도 있습니다. VFS의 강력한 기능을 확인하고 주요 인터페이스와 프로세스를 학습합니다.
Linux 파일 시스템에는 인터페이스 세트가 추상화되어 있으며 그 결과 유연성과 확장성이 지원되게 되었다. 이러한 인터페이스 세트의 핵심은 VFS(Virtual File System Switch)이다.
VFS는 다양한 파일 시스템 세트에서 파일 I/O를 실행할 수 있도록 상위 계층 애플리케이션에 표준 인터페이스 세트를 제공한다. 그리고 VFS는 하나 이상의 기본 장치에서 동시에 다수의 파일 시스템을 지원하는 방식으로 이 인터페이스를 제공한다. 또한 이 파일 시스템은 정적일 필요가 없으며 스토리지 장치의 일시적 특성에 따라 변화할 수 있다.
예를 들면 통상 Linux 데스크탑은 사용 가능한 하드 디스크에서 EXT3 파일 시스템을 지원하고 사용 가능한 CD-ROM(CD-ROM 파일 시스템또는 CDFS라고도 함)에서 ISO9660 파일 시스템을 지원한다. CD-ROM을 삽입하거나 제거함에 따라 Linux 커널은 다른 컨텐츠와 구조로 이루어진 새로운 파일 시스템에 적응해야 한다. 원격 파일 시스템은 NFS(Network File System)를 통해 액세스할 수 있다. 동시에 Linux는 로컬 하드 디스크에서 Windows®/Linux 듀얼 부트 시스템의 NTFS(NT File System) 파티션을 마운트하여 읽거나 쓸 수 있다.
마지막으로, 제거할 수 있는 UFD(USB Flash Drive)는 핫 플러그가 가능하며 또 다른 파일 시스템을 제공한다. 이러한 모든 상황에서 동일한 파일 I/O 인터페이스 세트를 이러한 장치상에서 사용할 수 있으며 기본 파일 시스템과 실제 장치를 사용자와 분리하여 추상화할 수 있다. (그림 1 참조)
그림 1. 다양한 파일 시스템과 스토리지 장치상에서 동일한 인터페이스를 제공하는 추상 계층 추상화의 계층 구조
이제 Linux VFS에서 제공하는 추상화 기능에 몇 가지 실제적인 아키텍처를 덧붙여 보자. 그림 2는 VFS 관점에서 Linux 스택의 상위 계층을 바라본 모습이다. VFS 위에 있는 계층은 Linux 표준 커널 SCI(system-call interface)이다. 이 인터페이스를 통해 사용자 공간에서의 호출이 다른 주소 공간에 있는 커널로 전환될 수 있다. 이 도메인에서 POSIX open
호출을 호출하는 사용자 공간 애플리케이션은 GNU C 라이브러리(glibc
)를 통해 커널과 시스템 호출 역다중화에 전달된다. 결국 VFS는 sys_open
호출을 사용하여 호출된다.
그림 2. 계층화된 VFS 아키텍처 VFS는 추상 계층을 제공하며 이로 인해 POSIX API는 특정 파일 시스템에서 해당 동작을 구현하기 위해 필요한 세부사항과 독립적으로 동작하게 된다. 여기서 핵심은 Open, Read, Write 또는 Close API 시스템 호출이 EXT3나 Btrfs에 있다는 점이다. VFS는 기본 파일 시스템에서 상속된 일반 파일 모델을 제공한다. (기본 파일 시스템에서는 다양한 POSIX API 함수의 동작을 구현해야 한다.) VFS 밖에서 추상화 정도를 높이면 기본적인 실제 장치(디스크, 디스크 파티션, 네트워크 스토리지 엔티티, 메모리 또는 기타 정보 저장 미디어(임시 저장 미디어 포함)가 파일 시스템과 독립적으로 동작하게 된다.
기본 파일 시스템의 세부적인 파일 조작을 추상화할 뿐만아니라 VFS는 기본 블록 장치를 사용 가능한 파일 시스템에 연결한다. 이제 VFS 내부를 살펴보고 그 동작 방식을 알아보자.
위로
VFS 내부
VFS 서브시스템의 전체 아키텍처를 살펴보기 전에 사용되는 주요 오브젝트를 살펴보자. 이 섹션에서는 수퍼블록, 인덱스 노드(또는inode), 디렉토리 항목(dentry) 및 file 오브젝트를 검토한다. 캐시와 같은 일부 추가 요소도 여기에서는 중요하며 나중에 전체 아키텍처에서 살펴볼 것이다.
수퍼블록
수퍼블록은 파일 시스템에 관한 상위 계층 메타데이터 컨테이너이다. 수퍼블록은 디스크(실제로는 리던던시를 위해 디스크의 여러 곳에 분산되어 있음)와 메모리에 존재하는 일종의 구조이다. 수퍼블록은 총 블록 수, 자유 블록, 루트 인덱스 노드와 같은 파일 시스템 매개변수를 정의하여 온 디스크 파일 시스템을 처리하기 위한 기초를 제공한다.
디스크에서 수퍼블록은 파일 시스템의 구조에 관한 정보를 커널에 제공한다. 메모리에서는 사용 중인(마운트된) 파일 시스템을 관리하는 데 필요한 정보와 상태를 제공한다. Linux에서는 마운트된 다수의 파일 시스템을 동시에 지원하기 때문에 각 super_block
구조가 하나의 목록에서 유지된다. (super_blocks
와 그 구조는 각각 ./linux/fs/super.c와 ./linux/include/fs/fs.h에 정의되어 있다.)
그림 3에는 수퍼블록과 그 요소가 간단하게 표시되어 있다. super_block
구조는 다른 정보를 캡슐화하는 다수의 기타 구조를 참조한다. 예를 들면 file_system_type
구조는 super_block
을 가져오거나 제거할 수 있는 다양한 잠금 기능과 함수는 물론이고 EXT3과 같은 파일 시스템 이름도 유지한다. file_system_type
오브젝트는 잘 알려진 register_file system
과 unregister_file system
함수(./linux/fs/file systems.c 참조)를 통해 관리된다. super_operations
구조는 다시 마운트하기와 같은 상위 레벨 조작은 물론 inode를 읽고 쓰는 데 필요한 다양한 함수를 정의한다. 이 파일 시스템에 상주하는 블록 장치와 마찬가지로 루트 디렉토리 항목(dentry
) 오브젝트도 여기서 캐시된다. 마지막으로 s_inodes
(모든 inode 목록), s_dirty
(모든 dirty inode 목록), s_io
및 s_more_io
(다시 쓰기를 처리하기 위해 파크된)를 포함한 inode와 s_files
(해당 파일 시스템의 모든 개방된 파일 목록)을 관리하는 데 필요한 많은 목록을 제공한다.
그림 3. super_block의 구조와 관련 요소에 대한 간략한 보기 커널에서는 vfsmount
라고 하는 관리 오브젝트가 마운트된 파일 시스템에 관한 정보를 제공한다는 점에 유의한다. 이러한 오브젝트 목록은 수퍼블록을 참조하여 해당 파일 시스템에 있는 /dev 장치의 이름, 마운트 위치 및 기타 상위 레벨 첨부 정보를 정의한다.
인덱스 노드(inode)
Linux는 inode(인덱스 노드)라고 하는 오브젝트를 통해 파일 시스템의 모든 오브젝트를 관리한다. inode는 다른 오브젝트로 연결되는 기호 링크나 디렉토리 또는 파일을 참조한다. 파일은 장치나 메모리와 같은 다른 유형의 오브젝트를 표현하는 데 사용되기 때문에 inode도 이러한 오브젝트를 표현하는 데 사용된다는 점을 유의한다.
여기서 말하는 inode는 VFS 계층 inode(인 메모리 inode)를 의미한다. 또한 각 파일 시스템은 디스크의 inode를 포함하고 있으며 해당 파일 시스템에 특정된 오브젝트에 관한 세부사항을 제공한다.
VFS inode는 inode_cache
에서 슬랩 할당자를 사용하여 할당된다. (슬랩 할당자에 관한 자세한 링크 정보는 참고자료를 확인한다.) inode는 inode를 기술하는 데이터와 조작, inode 컨텐츠 그리고 inode에서 가능한 다양한 조작으로 이루어져 있다. 그림 4에는 다수의 목록으로 구성된 VFS inode가 간단하게 표시되어 있으며 이 중 하나는 이러한 inode를 참조하는 dentry를 참조하고 있다. 여기에 포함된 오브젝트 레벨 메타데이터는 소유자 및 사용 권한 데이터(group-id, user-id, 및 사용 권한)와 마찬가지로 잘 알려진 처리 시간(작성 시간, 액세스 시간, 수정 시간)으로 구성되어 있다. inode는 inode에서 가능한 파일 조작을 참조하며 이들 대부분은 open
, read
,write
및 flush
와 같은 시스템 호출 인터페이스에 직접 맵핑된다. 또한 inode 지정 조작(create
, lookup
, link
, mkdir
등)도 참조한다. 마지막으로 주소 공간 오브젝트에서 표현되는 오브젝트의 실제 데이터를 관리하기 위한 구조가 있다. 주소 공간 오브젝트는 페이지 캐시 내에서 다양한 inode 페이지를 관리하는 오브젝트이다. 주소 공간 오브젝트는 파일 페이지를 관리하고 파일 섹션을 개별 프로세스 주소 공간에 맵핑하기 위해 사용된다. 주소 공간 오브젝트는 자체 조작 세트(writepage
, readpage
, releasepage
등)와 함께 동작한다.
그림 4. VFS inode의 간략한 표현 이 모든 정보는 ./linux/include/linux/fs.h에서 확인할 수 있다.
디렉토리 항목(dentry)
파일 시스템의 계층 특성은 dentry 오브젝트라고 하는 또 다른 오브젝트가 관리한다. 파일 시스템에는 수퍼블록에서 참조된 하나의 루트 dentry가 있으며 이 루트 dentry는 상위 계층이 없는 유일한 dentry이다. 기타 모든 dentry에는 상위 계층이 있으며 그 중에는 하위 계층을 갖고 있는 것도 있다. 예를 들어 /home/user/name으로 구성된 파일을 열면 4개의 dentry 오브젝트(루트 디렉토리 /
, 루트 디렉토리의 home
항목, user
디렉토리의 name
항목 마지막으로 사용자 디렉토리의 name
항목에 대한 dentry)가 작성된다. 이런 식으로 사용 중인 계층 파일 시스템에 dentry가 명확하게 맵핑된다.
dentry 오브젝트는 ./linux/include/fs/dcache.h에 기술된 dentry 구조에서 정의된다. 이 dentry 구조는 파일 이름과 같은 실제 데이터는 물론이고 파일 시스템에서 해당 항목과 다른 항목의 관계를 추적하는 다양한 요소로 구성되어 있다. 그림 5에 dentry 오브젝트가 간략하게 표시되어 있다. dentry는 해당 오브젝트가 포함된 특정 파일 시스템 인스턴스를 정의하는 super_block
을 참조한다. 그 다음에는 목록(오브젝트가 디렉토리인 경우)에 포함된 하위 dentry가 해당 오브젝트의 상위 dentry(상위 디렉토리) 다음에 나온다. 그런 다음 dentry 조작이 정의된다. (hash
, compare
, delete
, release
등과 같은 조작으로 이루어진다.)그런 다음 오브젝트 이름이 정의되며 이 이름은 inode 대신 해당 dentry에서 유지된다. 마지막으로 VFS inode에 참조가 제공된다.
그림 5. dentry 오브젝트의 간략한 표현 dentry 오브젝트는 파일 시스템 메모리에만 존재하며 디스크에는 저장되지 않는 다는 점에 유의한다. 파일 시스템 inode만 영구적으로 저장되며 여기서 dentry 오브젝트는 성능 개선을 위해 사용된다. ./linux/include/dcache.h에 dentry 구조에 대한 세부사항이 기술되어 있다.
file 오브젝트
Linux 시스템의 각 열린 파일에는 file
오브젝트가 존재한다. 이 오브젝트에는 해당 사용자의 open 인스턴스에 특정된 정보가 포함되어 있다. 그림 6에는 file 오브젝트가 간략하게 표시되어 있다. 보는 바와 같이 path
구조에는 dentry
와 vfsmount
에 대한 참조가 포함되어 있다. 잘 알려진 파일 조작(open
, close
, read
, write
, flush
등)으로 구성된 파일 조작 세트가 각 파일을 대상으로 정의된다. 그룹과 소유자를 포함하여 플래그와 사용 권한 세트가 정의된다. 마지막으로 특정 파일 인스턴스에 파일의 현재 오프셋과 같은 상태 저장 데이터가 저장된다.
그림 6. file 오브젝트의 간략한 표현 위로
오브젝트 관계
이제까지 VFS 계층의 여러 가지 중요한 오브젝트를 검토했으므로 이 오브젝트가 하나의 다이어그램 속에서 어떻게 서로 연관되는지 살펴보자. 지금까지는 상향식으로 오브젝트를 검토했으므로 이제 사용자 관점에서 역 방향으로 살펴보자. (그림 7 참조)
맨 위에 file
오브젝트가 열려있고 이 오브젝트를 프로세스 파일 디스크립터 목록에서 참조한다. file
오브젝트는 dentry
오브젝트를 참조하고 dentry 오브젝트는 inode
를 참조한다. inode
와 dentry
오브젝트는 기본 super_block
오브젝트를 참조한다. 두 명의 사용자가 같은 파일을 공유하는 경우와 같이 다수의 file 오브젝트가 동일한 dentry를 참조할 수도 있다. 또한 그림 7에서와 같이 dentry
오브젝트가 다른 dentry
오브젝트를 참조할 수도 있다. 이 경우 디렉토리는 파일을 참조하고 이 파일은 특정 파일의 inode를 참조한다.
그림 7. VFS의 주요 오브젝트 관계 위로
VFS 아키텍처
VFS의 내부 아키텍처는 파일 시스템의 조작 성능을 개선할 수 있는 파일 시스템 추상화와 다양한 캐시를 제공하는 디스패치 계층으로 구성되어 있다. 이 섹션에서는 내부 아키텍처와 주요 오브젝트가 상호 동작하는 방식을 살펴본다. (그림 8 참조)
그림 8. VFS 계층의 상위 레벨 보기 VFS에서 동적으로 관리되는 주요 오브젝트에는 dentry
와 inode
오브젝트가 있다. 이 오브젝트는 캐시되어 기본 파일 시스템에 대한 액세스 성능을 개선한다. 파일이 열리면 dentry 캐시에는 경로를 나타내는 디렉토리 레벨을 표현하는 항목이 채워진다. 또한 파일을 표현하는 오브젝트의 inode가 작성된다. 해시 테이블을 사용하여 dentry 캐시가 만들어지고 오브젝트의 이름으로 해시된다. dentry 캐시 항목은 dentry_cache
슬랩 할당자에서 할당되며 LRU(least-recently-used) 알고리즘을 사용하여 메모리가 부족한 경우에는 항목을 삭제한다. dentry 캐시와 관련된 함수는 ./linux/fs/dcache.c와 ./linux/include/linux/dcache.h에서 확인할 수 있다.
inode 캐시는 빨리 찾기 위해 필요한 해시 테이블과 두 개의 목록으로 구현된다. 첫 번째 목록은 현재 사용 중인 inode를 정의하고 두 번째 목록은 사용하지 않는 inode를 정의한다. 또한 사용 중인 inode는 해시 테이블에 저장된다. 개별 inode 캐시 오브젝트는inode_cache
슬랩 할당자에서 할당된다. ./linux/fs/inode.c와 ./linux/include/fs.h에서 inode 캐시와 관련된 함수를 확인할 수 있다. 현재 dentry 캐시는 inode 캐시의 마스터로 구현된다. inode 캐시에 dentry
오브젝트가 존재하면 inode
오브젝트 또한 존재한다. 찾아보기는 dentry 캐시에서 실행되며 그 결과로 inode 캐시에 오브젝트가 생긴다.
위로
추가 주제
이 기사에서는 서로 다른 파일 시스템을 일정하게 액세스할 수 있도록 사용된 오브젝트와 VFS, 그 접근 방식을 대략 살펴보았다. Linux는 이와 같이 서브시스템에서 확장 가능한 유연한 운영 체제이다. 참고자료 섹션에는 추가로 학습할 수 있는 세부 자료가 있다.
참고자료
교육
제품 및 기술 얻기
- developerWorks에서 직접 다운로드할 수 있는 IBM 시험판 소프트웨어를 사용하여 Linux와 관련된 후속 개발 프로젝트를 구현해 볼 수 있다.
토론
- 사용자의 개인 프로파일과 사용자 정의 홈 페이지가 제공되는 My developerWorks community에서는 관심을 가지고 있는 developerWorks의 여러 주제를 추적할 수 있으며 다른 developerWorks 사용자들과 의견을 나눌 수도 있다.
필자소개
M. Tim Jones는 임베디드 펌웨어 아키텍트이자 Artificial Intelligence: A Systems Approach, GNU/Linux Application Programming(현재 2판), AI Application Programming(현재 2판) 및 BSD Sockets Programming from a Multilanguage Perspective의 저자이다. 정지 위성을 위한 커널 개발에서 시작해 임베디드 시스템 아키텍처와 네트워크 프로토콜 개발에 이르기까지 다양한 분야에 대한 공학 지식을 가지고 있다. 콜로라도주 롱몬트 소재의 Emulex Corp.에서 선임 아키텍트로 활약하고 있다.
출처 - http://www.ibm.com/developerworks/kr/library/l-virtual-filesystem-switch/