非常に単純なファイルシステム ドライバー カーネル モジュールを実装しようとしています。マウントフォルダー内にファイルを作成し、マウントされたデバイスへの読み取り/書き込みアクセスを提供するだけです。いくつかのファイルに接続されたループ デバイスを考えてみましょう。次に、このデバイスが新しいファイルシステムタイプを使用して何らかのディレクトリにマウントされている場合、ユーザーは、単一のファイルシステムファイルを一種のインターフェイスとして使用して、ループに接続されたファイルを読み取り/書き込み/変更できるようになります。ファイルへのアクセスは、メモリ ページ メカニズムを使用して実装する必要があります。
これまでのところ、FS 単一ファイルを正常に作成できました。ルート用の inode と dentry と、ルート フォルダ内のファイルがあります。ここで、ファイル アクセスの操作を提供する必要があります。そこで、file_operations
file として使用する型構造を作成しましたinode->f_ops
。read/write/aio_read/aio_write
関数がありますが、関数はread
単に呼び出しdo_sync_read
、. それは書くことにも言えることです。aio_read
generic_file_aio_read
static struct file_operations fs_file_ops = {
.read = do_sync_read,
.aio_read = generic_file_aio_read,
.write = do_sync_write,
.aio_write = generic_file_aio_write,
}
address_space_operations
また、として使用する構造を作成しましたinode->i_mapping->a_ops
。機能がreadpage
ありwritepage
ます。私のreadpage
実装はmpage_readpage
標準関数を呼び出します。引数と関数mpage_readpage
で呼び出されます。readpage
page
get_block
static struct address_space_operations fs_aops = {
.readpage = fs_readpage,
.writepage = fs_writepage
};
static int fs_readpage(struct file *file, struct page *page)
{
return mpage_readpage(page, fs_get_block);
}
get_block
関数はスーパーブロックをバッファにマップし、メモリ ページ処理用のブロックを提供します。これは次の方法で実装されます。
static int fs_get_block(struct inode *inode, sector_t block, struct buffer_head *bh, int create)
{
map_bh(bh, inode->i_sb, block);
size_t i_b_size = bh->b_size >> inode->i_blkbits;
size_t r_b_size = i_size_read(inode) >> inode->i_blkbits - block;
bh->b_size = min(i_b_size, r_b_size) << inode->i_blkbits;
return 0;
}
したがって、ユーザーがファイルから何かを読み取ろうとすると、do_sync_read
が呼び出され、 が使用されますgeneric_file_aio_read
。これは関数を呼び出し、readpage
関数はページのブロックを提供する引数として取る をreadpage
呼び出します。この関数は、ページごとにファイルの読み取りを実装する必要があります。mpage_readpage
fs_get_block
問題は、今のところ、FS ファイルから必要な出力を取得できていないことです。では、私の実装の何が問題なのですか? 不完全な場合、それを機能させるためにモジュールにどの関数を実装する必要がありますか? または、おそらく、問題は私の実装にあるget_block
?