FUSE 조사 분석서
FUSE는 Filesystem in USErspace의 약자로, 커널이 아닌 유저 레벨에서 파일 시스템을 구현할 수 있게 만드는 하나의 커널 모듈이자 라이브러리이다.
FUSE를 이해하기 위해서는 먼저 VFS를 알아야 한다. VFS는 Virtual File System(가상 파일 시스템)의 약자로, 리눅스가 지원하는 각각의 파일 시스템을 일관된 형태로 인식하게 하는 인터페이스로 볼 수 있다.
VFS는 공통된 파일 모델을 제시하며, VFS에 매핑되는 파일 시스템은 이 모델의 요구사항을 충족해야 한다. 즉, 파일 시스템이 갖는 물리적 특성을 VFS의 논리적 특성으로 변환해야 한다.
위 사진은 해당 모델에 대한 그림으로, 다음의 객체들에 대한 개념을 정의한다.
- 슈퍼 블록 객체: 파일 시스템을 서술하는 객체이다.
- 아이노드 객체: 특정 파일의 데이터에 대한 정보를 갖는 객체이다.
- 파일 객체: 열린 파일과 프로세스 간 상호작용에 대한 정보를 갖는 객체이다.
- 디엔트리 객체: 디렉토리와 하위 파일(혹은 디렉토리)에 대한 연결을 저장하는 객체이다.
위 그림은 Linux 커널에 구현된 VFS의 공통 모델과 관련된 구조체 사이의 관계를 보여준다. 파일 시스템은 이러한 구조체들이 필요로 하는 정보들을 정확히 제공하기만 하면 VFS를 통해 마운트되고 파일 작업을 수행할 수 있게 된다.
예를 들어, 사용자가 read()
시스템 콜을 호출하면 위와 같이 연쇄적으로 함수가 호출되는데, VFS는 각 파일 시스템의 읽기 작업에 대한 로직을 함수 포인터로 갖고 있어 실제 파일 시스템이 변하더라도 성공적으로 파일의 데이터를 읽어올 수 있다.
물론 VFS의 모델이 각 파일 시스템에 대한 최적화된 작업을 항상 보장하지는 않는다는 등의 문제점이 있긴 하지만, 그보다 파일 시스템의 추상화 자체가 갖는 이점이 크기 때문에 Linux 커널에 포함되어 있다.
FUSE는 앞서 설명한 VFS 기능을 통해 작동한다. 커널 내의 FUSE 모듈이 VFS를 통해 하나의 파일 시스템으로 추상화되며, 그 내부에 구현된 공통 모델이 FUSE 라이브러리를 통해 사용자가 작성한 함수를 호출하는 방식으로 작동한다.
이를 통해 기존에 커널 레벨에 대한 이해와 커널 자체의 수정을 필요로 했던 파일 시스템의 한계를 극복하여 유저 레벨에서 커스터마이징을 가능케 하는 것이 FUSE의 핵심이다.
FUSE 라이브러리는 다수의 구조체 및 함수를 정의하는데, 그 중 핵심이 되는 구조체는 fuse_operations
구조체이다. 이 구조체는 함수 포인터로 구성되어 있어, 결과적으로 FUSE 커널 모듈이 호출하게 되는 사용자 함수를 결정하는 역할을 한다. 이 구조체에는 약 40개의 함수 포인터가 정의되어 있으며, 다음은 그 목록의 일부이다.
하지만 FUSE가 모든 함수에 대한 구현을 요구하지는 않는다. 구현하지 않은 함수에 대한 포인터를 NULL
로 제공하면, 해당 함수를 필요로 하는 작업을 수행하지 않는 경우 전혀 문제가 발생하지 않는다. 예를 들어, 다음은 FUSE에서 제공하는 예제 파일에서 fuse_operations
구조체를 초기화하는 것을 보여준다.
위 코드에서 볼 수 있듯이, main
함수에서는 fuse_main
을 호출하면 된다. 이 함수를 호출함으로써 인자로 지정해준 경로 이하부터는 하나의 파일 시스템으로 인식되며 FUSE 커널 모듈의 명령에 대응할 수 있는 상태가 된다.