Linux kernel v4.4에서 간단한 블록 장치 드라이버 만들어보기

ext2의 콜스택

파일시스템과 페이지캐시의 관계를 아주아주 간단하게 한번 추적해보겠습니다. 제일 단순한 ext2 파일시스템의 경우만 보겠습니다.

ext2의 file_operations를 한번 볼까요.

~/work/linux-torvalds $ /bin/grep file_operations fs/ext2/* -R
fs/ext2/dir.c:const struct file_operations ext2_dir_operations = {
fs/ext2/ext2.h:extern const struct file_operations ext2_dir_operations;
fs/ext2/ext2.h:extern const struct file_operations ext2_file_operations;
fs/ext2/file.c:const struct file_operations ext2_file_operations = {
fs/ext2/inode.c:    		inode->i_fop = &ext2_file_operations;
fs/ext2/inode.c:			inode->i_fop = &ext2_file_operations;
fs/ext2/namei.c:		inode->i_fop = &ext2_file_operations;
fs/ext2/namei.c:		inode->i_fop = &ext2_file_operations;
fs/ext2/namei.c:		inode->i_fop = &ext2_file_operations;
fs/ext2/namei.c:		inode->i_fop = &ext2_file_operations;

소스를 뒤져보니 바로 file.c라는 파일에 정의되어있다는걸 알 수 있습니다.

const struct file_operations ext2_file_operations = {
    .llseek		= generic_file_llseek,
	.read_iter	= generic_file_read_iter,
	.write_iter	= generic_file_write_iter,
	.unlocked_ioctl = ext2_ioctl,
#ifdef CONFIG_COMPAT
	.compat_ioctl	= ext2_compat_ioctl,
#endif
	.mmap		= ext2_file_mmap,
	.open		= dquot_file_open,
	.release	= ext2_release_file,
	.fsync		= ext2_fsync,
	.splice_read	= generic_file_splice_read,
	.splice_write	= iter_file_splice_write,
};

시스템콜에서 read_iter와 write_iter를 호출할 것이니, generic_file_read_iter와 generic_file_write_iter부터 코드를 따라가보면 되겠네요.

generic_file_read_iter
-->do_generic_file_read
--> find_get_page
--> pagecache_get_page*

generic_file_write_iter
--> generic_perform_write 
--> a_ops->write_begin = ext2_write_begin 
--> block_write_begin 
--> grab_cache_page_write_begin 
--> pagecache_get_page*

참고로 a_ops는 inode.c 파일에 정의되어있습니다.

const struct address_space_operations ext2_aops = {
    .readpage		= ext2_readpage,
	.readpages		= ext2_readpages,
	.writepage		= ext2_writepage,
	.write_begin		= ext2_write_begin,
	.write_end		= ext2_write_end,
	.bmap			= ext2_bmap,
	.direct_IO		= ext2_direct_IO,
	.writepages		= ext2_writepages,
	.migratepage		= buffer_migrate_page,
	.is_partially_uptodate	= block_is_partially_uptodate,
	.error_remove_page	= generic_error_remove_page,
};

mybrd의 콜스택을 분석해본 결과와 중복되는 콜스택이 나타납니다.

읽기의 경우에는 do_generic_file_read부터, 쓰기에는 block_write_begin부터가 중복됩니다. 따라서 우리는 이 함수들부터 코드를 읽어보겠습니다.

댓글

댓글 본문
작성자
비밀번호
버전 관리
gurugio
현재 버전
선택 버전
graphittie 자세히 보기