擬似ファイルシステムを作ってみる(3)


Rev.2を表示中。最新版はこちら

ファイルopenでファイル名からファイルディスクリプタを取得します。ファイルディスクリプタが分かればfile構造体が分かります。file構造体がわかればinode構造体がわかり、そこのread,write等のコールバック関数をコールすることで、ファイルシステムに依存した読み書き込みが可能となるわけです。

モジュールがインストールされるとregister_filesystemが呼ばれます。これはfile_system_type構造体を引数とし、それにはファイルシステム名(ext2やext3)や、システムに依存するスーパブロック情報を設定するコールバック関数が定義されており、ファイルシステムリストに登録されます。
fs/filesystems.c
static struct file_system_type *file_systems;
int register_filesystem(struct file_system_type * fs)
{
       int res = 0;
       struct file_system_type ** p;

       BUG_ON(strchr(fs->name, '.'));
       if (fs->next)
               return -EBUSY;
       INIT_LIST_HEAD(&fs->fs_supers);
       write_lock(&file_systems_lock);
       p = find_filesystem(fs->name, strlen(fs->name));
       if (*p)
               res = -EBUSY;
       else
               *p = fs;
       write_unlock(&file_systems_lock);
       return res;
}
ファイルシステムリストのヘッドとしてfile_systems変数が静的に定義されています。register_filesystemはfind_filesystemでこのfile_systemsからファイルシステムにすでに登録されてないか、ファイルシステム名をキーとして検索します。もし登録されていればそのポインターが、そうでなければ最後のローケーションが返され、そこに登録するファイルシステムのポインターを設定することで、システムにファイルシステムリストとして登録しています。

mountが呼び出されると、そのファイルシステムタイプをキーにしてfile_system_typeを取得し、そこで定義されている.get_sbで設定しているmy_vfs_get_sbが呼び出され、get_sb_nodevにて本システムファイル属性(要はスーパブロック)がsuper_block構造体に設定していきます。内部処理的にsuper_block構造体はファイルシステムそのものとなるわけです。
sb->s_maxbytes = MAX_LFS_FILESIZE;
sb->s_blocksize = PAGE_CACHE_SIZE;
sb->s_blocksize_bits = PAGE_CACHE_SHIFT;
sb->s_magic = 0x484f4745; /* 'HOGE' */
sb->s_op = &my_vfs_ops;
なおsuper_block構造体にもsuper_operationsコールバックを設定します。これはファイルシステムの状態とかスーパブロックを操作する関数と思われます。

ディレクトリ操作に関する処理で、その読み出し書き込み等の処理をfile_operationsに、ディレクトリそのもの(たぶん削除、作成等)をinode_operationsに記述します。
static const struct file_operations my_vfs_dir_ops = {
      .readdir = my_vfs_dir_readdir,
};
static const struct inode_operations my_vfs_dir_inode_ops = {
      .lookup	 = my_vfs_dir_lookup,
};
ファイル操作に関する処理で、その読み出し書き込み等の処理をfile_operationsに、ファイルそのもの(たぶん削除、作成等)をinode_operationsに記述します。ファイルに削除、作成等はサポートしていませんので、inode_operations は設定していません。
static const struct file_operations my_vfs_file_ops = {
    .read	 = my_vfs_file_read,
    .write	 = my_vfs_file_write,
    .fsync	 = my_vfs_file_fsync
};
static const struct inode_operations my_vfs_file_inode_ops = {
};
注意することはこれらのオペレーションはinodeに設定される。ということです。ですからファイル名からinodeを取得する処理が必要です。それがmy_vfs_dir_lookupです。my_vfs_dir_lookupはdentryにセットされたファイル名をキーにしてそのinodeを取得します。my_vfs_internal_lookupになります。inode番後はa,b,c,d,eに100,101,102,103,104を割り当てています。この番号はrootが1として、あとはそれ以外の番号であればなんでもかまいません。理由はすべて同じファイルシステム上でコールバック処理が同じファイル(ディレクトリでない。)だからです。なお、.lookupコールバックはスーパブロック取得時にrootのinodeとして設定されます。

システムコールreadから.read = my_vfs_file_readが、writeから.write = my_vfs_file_write等々がコールされ、該当の処理がされます。readについて言えば、引数のfile構造体からdentryがそしてinode番号が取得し、該当するデータブロックを読み込めばいいわけです。なおサンプルでのファイル名で該当するファイルを検索し、そのデータをファイルとして読み込んでいます。
static ssize_t my_vfs_file_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
ざっとこんな感じです。なお憶測で書いているところもあります。

最終更新 2010/01/16 16:28:10 - north
(2010/01/16 16:26:53 作成)


検索

アクセス数
3689612
最近のコメント
コアダンプファイル - sakaia
list_head構造体 - yocto_no_yomikata
勧告ロックと強制ロック - wataash
LKMからのファイル出力 - 重松 宏昌
kprobe - ななし
ksetの実装 - スーパーコピー
カーネルスレッドとは - ノース
カーネルスレッドとは - nbyst
asmlinkageってなに? - ノース
asmlinkageってなに? - よろしく
Adsense
広告情報が設定されていません。