리눅스 커널의 가상 파일 시스템 (VFS) 이해

리눅스 가상 파일 시스템 (VFS)

리눅스 커널의 가상 파일 시스템(Virtual File System, VFS)은 다양한 저장 장치와 파일 시스템 유형을 사용자 애플리케이션에 일관된 방식으로 제공하기 위한 추상화 계층입니다. 이 계층 덕분에 애플리케이션은 실제 파일 시스템의 종류(예: ext4, NTFS, XFS 등)에 관계없이 동일한 시스템 호출 인터페이스를 사용하여 파일 및 디렉터리에 접근할 수 있습니다.

VFS의 주요 이점은 다음과 같습니다:

  • 애플리케이션 개발 단순화: 개발자는 통일된 API를 통해 여러 저장 매체에 접근할 수 있습니다.
  • 새로운 파일 시스템 통합 용이성: 새로운 파일 시스템을 커널에 추가할 때, VFS가 정의한 표준 인터페이스만 구현하면 되므로 커널 핵심부를 수정할 필요가 없습니다.

VFS의 핵심 구성 요소: 네 가지 주요 객체

VFS는 파일 시스템의 다양한 측면을 관리하기 위해 네 가지 핵심 객체를 사용합니다. 이들은 파일 시스템의 구조와 동작을 추상화하는 데 필수적인 역할을 합니다.

1. 슈퍼블록 (Superblock)

슈퍼블록은 파일 시스템 전체에 대한 메타데이터를 담고 있는 객체입니다. 이는 파일 시스템의 특정 인스턴스에 대한 정보를 포함하며, 파일 시스템이 마운트될 때 생성됩니다. 일반적으로 디스크의 특정 섹터에 저장되지만, procfssysfs와 같은 메모리 기반 파일 시스템의 경우 사용 시 메모리에 동적으로 생성됩니다.

다음은 슈퍼블록 구조체의 핵심 필드와 관련 메서드를 보여주는 예시입니다:


/*
 * VFS 슈퍼블록 정보를 담는 구조체 정의
 */
struct vfs_superblock_info {
    struct list_head         superblock_list_entry; /* 모든 슈퍼블록을 연결하는 리스트 */
    const struct superblock_methods_table *op_table; /* 슈퍼블록 관련 연산 함수 테이블 */
    struct dentry            *mount_root_dentry;    /* 파일 시스템 마운트 지점의 디렉터리 항목 */
    struct mutex             access_mutex;          /* 슈퍼블록 동기화를 위한 뮤텍스 */
    int                      ref_count;             /* 슈퍼블록 참조 횟수 */

    struct list_head         active_inodes;         /* 이 파일 시스템의 활성 아이노드 리스트 */
    struct mtd_info          *storage_device_info;  /* 저장 장치 관련 정보 */
    fmode_t                  mount_flags;           /* 파일 시스템 마운트 권한 및 플래그 */
};

/*
 * 슈퍼블록이 구현해야 하는 연산 메서드들
 */
struct superblock_methods_table {
    struct inode *(*create_new_inode)(struct vfs_superblock_info *sb_ptr); /* 새 아이노드 객체 생성 및 초기화 */
    void (*release_inode_object)(struct inode *inode_obj);               /* 지정된 아이노드 객체 해제 */

    void (*mark_inode_dirty)(struct inode *inode_obj);                   /* 아이노드가 수정되었음을 VFS에 알림 */
    int (*persist_inode_to_disk)(struct inode *inode_obj, int sync_wait); /* 아이노드를 디스크에 기록 (동기화 여부 지정) */
    void (*on_last_ref_drop)(struct inode *inode_obj);                   /* 아이노드에 대한 마지막 참조가 사라졌을 때 호출 */
    void (*remove_inode_from_storage)(struct inode *inode_obj);         /* 지정된 아이노드를 디스크에서 삭제 */
    void (*cleanup_superblock)(struct vfs_superblock_info *sb_ptr);       /* 파일 시스템 언마운트 시 슈퍼블록 해제 */
    void (*update_disk_superblock)(struct vfs_superblock_info *sb_ptr);   /* 디스크의 슈퍼블록 정보 갱신 */
    int (*synchronize_filesystem)(struct vfs_superblock_info *sb_ptr, int wait_for_completion); /* 파일 시스템 데이터 동기화 */
    int (*query_fs_status)(struct dentry *dir_entry, struct kstatfs *status_buf); /* 파일 시스템 상태 정보 조회 */
    int (*reconfigure_mount)(struct vfs_superblock_info *sb_ptr, int *flags_ptr, char *data_options); /* 새로운 옵션으로 파일 시스템 재마운트 */
    void (*invalidate_inode_data)(struct inode *inode_obj);              /* 아이노드 관련 데이터 페이지 해제 및 초기화 */
    void (*initiate_unmount)(struct vfs_superblock_info *sb_ptr);         /* 언마운트 작업 시작 (중단 가능) */
};

2. 아이노드 (Inode)

아이노드는 VFS의 핵심 개념 중 하나로, 파일 시스템 내의 모든 파일이나 디렉터리에 대한 메타데이터를 담고 있는 객체입니다. 여기서 '파일'은 일반 파일뿐만 아니라 디렉터리, 심볼릭 링크, 특수 장치 파일 등 파일 시스템이 관리하는 모든 유형의 데이터를 의미합니다. 아이노드 자체는 데이터 블록을 직접 포함하지 않고, 해당 데이터 블록의 위치를 가리키는 포인터를 포함합니다.

슈퍼블록과 마찬가지로 아이노드도 실제로는 디스크에 저장되어 있다가, 파일이나 디렉터리에 접근될 때 메모리에 로드되어 vfs_inode_object 구조체로 표현됩니다.

다음은 아이노드 구조체의 중요한 필드와 관련 연산자들의 예시입니다:


/*
 * VFS 아이노드 객체 정보를 담는 구조체 정의
 */
struct vfs_inode_object {
    struct hlist_node          hash_table_entry;        /* 아이노드 빠른 검색을 위한 해시 테이블 엔트리 */
    struct list_head           global_inode_list;       /* 모든 아이노드를 연결하는 리스트 */
    struct list_head           superblock_inode_list;   /* 특정 슈퍼블록에 속한 아이노드 리스트 */
    struct list_head           associated_dentries;     /* 이 아이노드에 연결된 디렉터리 항목 리스트 */
    unsigned long              unique_id;               /* 아이노드 번호 */
    atomic_t                   reference_count;         /* 아이노드 참조 횟수 */
    unsigned int               hard_link_count;         /* 하드 링크 수 */
    uid_t                      owner_uid;               /* 소유자 사용자 ID */
    gid_t                      group_gid;               /* 소유 그룹 ID */
    struct timespec            last_access_time;        /* 마지막 접근 시간 */
    struct timespec            last_modification_time;  /* 마지막 수정 시간 */
    struct timespec            creation_time;           /* 생성 시간 (또는 마지막 상태 변경 시간) */
    const struct file_object_operations *inode_method_table; /* 아이노드 관련 연산 함수 테이블 */
    const struct file_operations *file_method_default;    /* 기본 파일 연산 함수 (파일인 경우) */
    struct vfs_superblock_info *parent_superblock;       /* 관련 슈퍼블록 포인터 */
    struct address_space       *address_space_map;      /* 파일 데이터의 주소 공간 매핑 */
    struct address_space       device_address_map;      /* 장치 주소 공간 매핑 */
    unsigned int               status_flags;            /* 파일 시스템 관련 플래그 */
    void                       *private_data_ptr;       /* 파일 시스템별 전용 데이터 포인터 */
};

/*
 * 아이노드가 구현해야 하는 연산 메서드들
 */
struct file_object_operations {
    /* 새 디렉터리 항목(dentry)에 대한 아이노드를 생성합니다. */
    int (*create_file_entry)(struct inode *parent_inode, struct dentry *new_dentry, int mode, struct nameidata *nd);
    /* 특정 디렉터리에서 주어진 파일명에 해당하는 아이노드를 찾습니다. */
    struct dentry *(*find_entry_in_dir)(struct inode *parent_inode, struct dentry *target_dentry, struct nameidata *nd);
    /* 하드 링크를 생성합니다. */
    int (*create_hard_link)(struct dentry *old_dentry, struct inode *target_inode, struct dentry *new_dentry);
    /* 심볼릭 링크를 따라가 대상 아이노드를 찾습니다. */
    void *(*resolve_symlink)(struct dentry *symlink_dentry, struct nameidata *nd);
    /* resolve_symlink 호출 후 정리 작업을 수행합니다. */
    void (*cleanup_symlink_context)(struct dentry *symlink_dentry, struct nameidata *nd, void *link_context);
    /* 파일의 크기를 변경합니다 (잘라내기/확장). */
    void (*resize_file_content)(struct inode *inode_obj);
};

3. 디렉터리 항목 (Dentry)

디렉터리 항목(dentry)은 파일 시스템 경로의 한 구성 요소를 나타내는 객체입니다. 슈퍼블록이나 아이노드와 달리, 디렉터리 항목은 디스크에 실제 저장되지 않고, 전적으로 메모리에서 관리됩니다. 이는 디렉터리 구조를 캐시하고 파일 경로를 아이노드에 매핑하는 데 사용됩니다. 각 디렉터리 항목은 파일 또는 디렉터리의 이름과 해당 아이노드를 연결하며, 디렉터리 트리의 계층 구조를 나타냅니다.

태그: Linux kernel VFS filesystem Superblock inode

7월 1일 21:00에 게시됨