動画・写真などのデータを仮想化する仕組みとは? = Linuxカーネルinodeの仕組み =:作りながら理解するファイルシステムの仕組み(9)(2/2 ページ)
今回は、前回紹介した「dentry」が参照している、ファイルの実体「inode」について詳しく解説する!
共通データ
inodeのメンバには、共通データが入っています。具体的には、ファイルサイズやモード情報などが設定されており、ファイル情報を参照するstat(2)システムコールで返すデータが一通りそろっています(注5)。
通常は、これらのデータでファイル情報をカバーできるのですが、LFS固有のデータもどこかに記録しておき、必要に応じて参照できるようにしておく必要があります。そのためのメンバが「i_private」というメンバです。
ただし、ファイルシステムによってはi_privateを使わずに、LFS固有データがinodeを包含するようなデータ構造を採用しているものもあります(注6)(図4)。
このような構造を採用するメリットとしては、LFS固有データとinodeデータのメモリが連続しているため、メモリフラグメント(注7)の抑止効果が挙げられます。
筆者が仕事でLinuxファイルシステムを開発していたのは、Linux 2.4系と古いのですが、その当時の記憶ではLinux標準でないファイルシステムの固有データはi_privateに登録することが普通だったと思います。しかし、Linux 2.6系ではVFS層のサポートもあり、全体的にinode包含型の採用率が高いようです。Linuxは、日々進歩していますね。ちなみに現時点でのtarfsは、inode包含型ではないので、いずれ改善させたいと思います。
共通オペレーション
inodeのオペレーションとしては、大きく分けて2つあります。
- ファイルの検索/作成/削除などを行うためのオペレーション(inode_operations)
- ファイルデータのI/Oを行うためのオペレーション(file_operations)
まず、inode_operationsの主要な関数を表3にまとめました。
関数名 | REG | DIR | SYM | オペレーション内容 |
---|---|---|---|---|
create | × | ○ | × | 通常ファイルを作成する |
lookup | × | ○ | × | ファイルを検索する |
unlink | × | ○ | × | ファイルを削除する |
symlink | × | ○ | × | シンボリックリンクを作成する |
mkdir | × | ○ | × | ディレクトリを作成する |
rmdir | × | ○ | × | ディレクトリを削除する |
mknod | × | ○ | × | デバイスファイルを作成する |
rename | × | ○ | × | ファイル名を変更する |
readlink | × | × | ○ | シンボリックリンクのパス名を参照する |
follow_link | × | × | ○ | シンボリックリンクのリンク先をたどる |
put_link | × | × | ○ | リンク先のパス格納バッファを解放する |
truncate | ○ | × | × | ファイルサイズを変更する |
permission | ○ | ○ | ○ | ファイルアクセス権をチェックする |
setattr | ○ | ○ | ○ | ファイルの時刻/モード/UID/GIDを変更する |
表3 inode_operations |
ご覧のとおり多数の関数(オペレーション)があります(注8)。ローカルファイルシステムを新たに追加する場合は、これらの関数を登録する必要があります。登録する関数は、ファイル種別ごとに異なります。通常ファイルの場合は、inode情報に関するデータの参照・変更操作だけです。シンボリックリンクは、inode情報操作に加えてリンク先パス名に対するオペレーション関数の登録が必要になります。そして、登録関数が一番多いディレクトリについては、inode操作およびファイルの検索・作成・削除・変名などのオペレーションを登録する必要があります。
file_operationsの主要な関数は、表4のとおりです。
関数名 | REG | DIR | SYM | オペレーション内容 |
---|---|---|---|---|
llseek | ○ | ○ | × | ファイルオフセット位置を変更する |
read | ○ | × | × | ファイルデータを読み込む |
write | ○ | × | × | ファイルデータを書き込む |
readdir | × | ○ | × | ディレクトリ内のファイル名一覧を取得する |
mmap | ○ | × | × | ファイルのメモリマップを作成する |
open | ○ | ○ | × | ファイルをオープンする |
release | ○ | ○ | × | ファイルをクローズする |
fsync | ○ | × | × | ファイルの変更データを永続化する |
表4 file_operations |
ファイルI/O用の関数なので、シンボリックリンクは関数の登録は不要です。一方、通常ファイルについては、動画や写真のデータを読み書きするための関数readやwriteを登録しなければなりません。最後にディレクトリについては、ファイル名一覧を参照する専用関数としてreaddirの登録が必要となります。
これらの登録関数ですが、ローカルファイルシステムを作る場合には、どうやったらよいか戸惑ってしまうのではないかと思います。筆者が経験的にやってきたこととしては、Linux標準のファイルシステムであるext3やVFS層からローカルファイルシステムの処理を呼び出すソースを読み、紙と鉛筆でデータ構造や関数呼び出し関係を図示しながら……、「あー、ここはこうすればよいのか!」といった風に設計・実装を進めていきました(注9)。
さて、次回は、ファイルデータのI/O処理を理解するうえで欠かせない「page」と「buffer_head」の構造について解説します。これが分かれば、Linuxカーネル内で自分のデータがどうやって管理されているかがよく分かります。お楽しみに! (次回に続く)
Copyright © ITmedia, Inc. All Rights Reserved.