23.12.22 최초 작성
interface 를 지원include/linux/fs.h
struct file
struct inode
struct address_space
page cache 관리하기 위한 자료구조struct dentry
inode 관계 관리하기 위한 자료구조struct super_block
task_struct의 files 자료구조에서 files_struct를 가르킴
files_struct는 파일 디스크립터를 가리키며 이 안에는 struct file자료구조와 inode, inode가 속한 struct super_block, f_dentry
struct file구조는 linkek list로 관리되며 파일 시스템을 조작하는 함수를 가리키는 함수 포인터(f_op), struct dentry를 가리키는 포인터(f_dentry)를 가짐
struct inode에는 inode와 파일 시스템을 조작하는 함수를 가리키는 함수 포인터(i_op, i_fop), 해당 inode가 속하는 struct super_block을 가리키는 포인터(i_sb), struct address_space를 나타내는 메모리 상의 주소를 가리키는 포인터(i_mapping) 존재
struct dentry에는 dentry를 조작하는 함수를 가리키는 함수 포인터(d_ops), 해당 inode가 속하는 struct super_block을 가리키는 포인터(d_sb), struct inode를 가리키는 포인터(d_inode)와 파일 이름을 저장하는 공간(NAME)을 관리
struct address_space에는 address_space를 조작하는 함수를 가리키는 함수 포인터(a_ops),struct inode를 가리키는 포인터(host), page를 관리하는 tree를 가리키는 포인터(page_tree)를 가짐
application
libarary
system call을 더 간략하게 추상화한 계층user mode와 kernel mode사이의 전환 수행system call
open(), read(), write())virtual file system
page/buffer cache를 통해 I/O 내용 기록specific file system
file로 추상화page/buffer cache를 통해 I/O 내용 기록block layer
page/buffer cache를 통해 I/O 내용 기록Journaling 담당 device driver
device를 디스크 블록(disk block)의 집합으로 추상화device
platter, track, sector, cylinder, spindle로 구성 됨head, arm을 통해 특정 구역의 데이터 읽음seek time, rotational latency, transmission time등의 성능 지표가 있음파일 시스템과 다른 요소들 간의 상호작용
| 시스템 콜 | Init | VM | Block Device |
|---|---|---|---|
| open (inode operation) read (file_operation) readdir (dentry_operation) | register, mount (superblock, fs_type) | readpage, writepage (address_space_operation) | bio_submit, bread, bwrite (request, bio) |
함수 구현
// /src/linux-source ~~/fs/(파일 시스템)
balloc.c //디스크 블록 관련 함수 관리
dir.c //디렉토리 관련 함수 관리
file.c //파일, inode 관련 함수 관리
inode.c //inode 관리하는 함수
namei.c //address space 관련 함수 관리
super.c //superblock 관련 함수 관리
ext2 기준
1. 파일 시스템 등록
module_init()에 등록된 init_ext2_fs()함수 실행fs/ext2/super.cinit_ext2_fs()에 register_filesystem()을 호출해 ext2_fs_type을 인자로 넘겨 줌ext2_fs_type은 정해져 있음static struct file_system_type ext2_fs_type = {
.owner = THIS_MODULE,
.name = "ext2",
.mount = ext2_mount,
.kill_sb = kill_block_super,
.fs_flags = FS_REQUIRES_DEV,
};
fs/filesystem.cregister_filesystem()에서 ext2_fs_type을 find_filesystem()에게 넘겨줘 2. mount
fs/namespace.c
sys_mount()를 통해 do_mount() 호출, do_mount()는 상태를 확인하고 path_mount()호출path_mount()를 통해 do_new_mount() 호출do_new_mount()는 register_filesystem()에서 등록한 파일 시스템 불러옴, vfs_get_tree() 호출fs/super.c
vfs_get_tree()에서 fc->ops->get_tree에 등록된 legacy_get_tree() 호출fs/fs_context.c
legacy_get_tree()에서 fc->fs->type->mount등록된 ext2_mount() 호출fs/ext2/super.c
ext2_mount()에서 mount_bdev()를 호출fs/super.c
mount_bdev()에서 인자를 전달해 ext2_fill_super() 호출fs/ext2/super.c
ext2_fill_super()에서 bread()를 호출해 superblock을 읽고 초기화, ext2_iget()을 통해 root의 inode를 찾고 d_make_root()를 통해 마운트 포인트에 연결1. 파일 찾기
fs/open.csys_open()에서 do_sys_open()호출, do_sys_open()에서 do_sys_openat2()호출do_sys_openat2()에서 get_unused_fd()로 쓰이지 않는 fd 찾고 do_filp_open()호출fs/namei.cdo_filp_open()를 통해 path_openat() 호출, path_openat()를 통해 link_path_walk() 호출link_path_walk()에서 walk_component()를 통해 링크를 탐색하면서 경로가 유효한지 확인walk_component()에서 lookup_fast()를 통해 캐시를 탐색해서 없으면 lookup_slow()를 호출lookup_slow()에서 i_op->lookup()에 등록된 ext2_lookup() 함수 호출fs/ext2/namei.cext2_lookup()에서 ext2_inode_by_name() 호출fs/ext2/dir.cext2_inode_by_name()에서 이름으로 인자를 받아 inode탐색, ext2_find_entry() 호출
fs/ext2/dir.c
ext2_find_entry()에서 ext2_get_page()호출해 페이지(블록) 탐색, ext2_match()를 호출해 찾고자 하는 파일 이름과 일치하는 inode 탐색2. 파일 수준 열기
fs/namei.c
do_open()에서 vfs_open()호출fs/open.c
vfs_open()에서 do_entry_open()호출해 f->op_open()에 등록된 함수 호출1. 시스템 호출 및 파일 조작
fs/read_write.c
sys_read()가 ksys_read()호출 ksys_read()가 vfs_read()호출, 권한 검사해 f_op->read에 등록된 read_iter() 함수 호출include/linux/fs.h
read_iter() : vectored I/O를 지원해 I/O 횟수를 줄여줌, ext2_file_read_iter()를 호출fs/ext2/file.c
ext2_file_read_iter() : ext2_dax_read_iter()를 통해 직접 저장장치에 접근하거나 ext2_dax_read_iter()를 통해 페이지 캐시를 확인함
mm/filemap.c
ext2_dax_read_iter()에서 generic_file_buffered_read() 호출generic_file_buffered_read()에서 get_page()를 통해 페이지 캐시를 탐색해 있으면 해당 페이지를 반환, 없으면 generic_file_buffered_read_no_cached_page() 호출generic_file_buffered_read()에서 a_ops->readpage()에 등록된 함수 ext2_readpage() 호출fs/ext2/inode.c
ext2_readpage()에서 mpage_readpage()호출mm/filemap.c
mpage_readpage()에서 I/O에 필요한 자료구조인struct bio를 조작하기 위해 do_mpage_readpage()호출do_mpage_readpage()에서 ext2_get_block()을 통해 조작할 블록 가져옴