カーネル開発(ファイルシステム)Linuxのカーネルの開発に関する世界観(ファイルシステム)です。Linuxカーネルも参照のこと。第2版」を編集して引用しました。open()プロセスがアクセスできるのはオープンされているファイルだけ。pathはファイルパスを指定する。flagはオープンする方法(読み取り専用、書き込み専用、読み書き両用、追記など)を指定し、ファイルが存在しない場合に新しく作ることもできる。modeは新しく作成するファイルのアクセス権。このシステムコールは、オープンファイルオブジェクトを作成し、ファイルディスクリプタと呼ばれる識別子を返す。オープンファイルオブジェクトには、以下が含まれる。・ファイルを処理するためのデータ。ファイルのデータがコピーされるカーネルのバッファメモリ領域や、次回の操作が行われるファイル中の現在位置を示すoffsetメンバ。ファイルポインタと呼ばれることもある。・プロセスから呼び出すことのできる複数のカーネル関数へのポインタ。呼び出し可能な関数の集合は、flag引数の値による。オープンファイルオブジェクトには、オープンされたファイルとプロセスとのやり取りや制御に関連するデータが含まれている。ファイルディスクリプタとは、どのやり取りかを指し示すもの。そのため、複数のファイルディスクリプタが同一プロセスの内で同じオープンファイルオブジェクトを指すこともある。複数のプロセスが同じファイルを同時にオープンすることもある。この時、ファイルシステムは、それぞれのプロセスに対して、別々のオープンファイルオブジェクトとともに、別々のファイルディスクリプタを割り当てる。このような場合、UNIXファイルシステムでは、複数のプロセスが同じファイルに対して行うI/O操作に関して、何ら同期処理の類いを提供しない。ファイルの全体あるいは一部に対してプロセス同士が同期をとれるように、flock()などのシステムコールを利用できるようになっている。プロセスは新しいファイルを作成するために、creat()システムコールを呼び出すこともできる。creat()はopen()と全く同様に、カーネルによって処理される。lseek()オープンされたファイルは、順序的(シーケンシャル)にもランダムにもアクセスできる。カーネルは次の読み書き操作が行われる現在位置を示すファイルポインタを、オープンファイルオブジェクト中に保持している。UNIXはファイルの順次アクセスを前提としており、read()とwrite()は必ず現在のファイルポインタの位置を参照する。現在位置を変更したい場合には、プログラムは明示的にlseek()システムコールを呼び出す必要がある。ファイルがオープンされると、カーネルはファイルポインタをファイル中の先頭の1バイト目(オフセット0)に設定する。lseek()は以下のような引数が必要。whence);fdはオープンされたファイルのファイルディスクリプタ。offsetはファイルポインタの新しい位置を計算するのに使用される符号付き整数値。・offsetの値に数値0を足す(ファイル先頭からのオフセット)・現在のファイルポインタにoffsetの値を加える・末尾のバイトの位置にoffsetの値を加える(ファイル末尾からのオフセット)がある。read()read()は以下のような引数が必要。count);fdはオープンされたファイルのファイルディスクリプタ、bufはプロセスのアドレス空間にある、データ転送先のバッファのアドレス、countは読み取るバイト数を表す。カーネルがread()システムコールを処理するには、オープンされているファイルのoffsetメンバの現在値から始まるcountバイトを、ファイルディスクリプタfdを持つファイルから読み取ろうとする。カーネルは、EOF、空のパイプなどの場合、countバイト数の読み取りに成功しないこともある。返されるnreadの値は、実際に読み取られたバイト数を示す。ファイルポインタも元の値にnreadを加えて更新される。write()write()の引数についても同様。count);bufの内容をcount分だけファイルディスクリプタfdによって参照されるファイルへと書き込む。成功した場合、書き込まれたバイト数が返る。close()プロセスは、ファイルの内容にアクセスする必要がなくなると、以下のシステムコールを呼び出すことができる。close(fd);これにより、ファイルディスクリプタfdに関連するオープンファイルオブジェクトが解放される。プロセスが終了すると、その時点でまだオープンされていたファイル全てがカーネルによってクローズされる。rename()とunlink()ファイルの名前を変えたり、ファイルを削除する際、プロセスはそのファイルをオープンする必要はない。実際、このような操作は、対象ファイルではなく1つまたは2つのディレクトリの中身に対する操作となる。ファイルリンクの名前を変更するには以下のようにする。newpath);次のようなシステムコールは、ファイルのリンク数を1減らし、ディレクトリの内の対応するエントリを削除する。ファイルが削除されるのは、リンクカウントの値が0になった時だけ。readなどのシステムコールを受け付けると、カーネルの中でインターフェースとなるファイルオブジェクトが作成される。カーネルがそのファイル情報を識別するための番号。writeを使う時にそのストリームを指すために使われる。FILE型のポインタはファイルディスクリプタのラッパー。ディレクトリー・エントリーの略で、ディレクトリパス情報を持つ。ストレージデバイスの内部で使われるファイルのインデックス。関連付けられ、ファイルオブジェクトのポインタを返す。カーネルの内部では効率化のために読み書き情報をキャッシュしており、iノードが実際に書きこまれたことを示すフラグのことをダーティビットと呼ぶ。sys_write()が、VFSの機能であるトランスレーションによって、ext2など具体的なファイルシステムの固有の関数に置き換えられる。ext2はLinuxで標準的に使われるブロック型ファイルシステム。データをデータブロックやスーパーブロックを持ったブロックグループに分けて管理する。このほかに、データベースで良く使われる「Bツリー」(B木)という技術を応用したさらに高速・堅固なファイルシステムがある。その中でもReiserFSやXFSなどが有名だが、将来の標準候補であると注目されているのがBtrFS。ジャーナリングに対応したext3/4のようなファイルシステムでは、システムを途中で強制停止した場合でもファイルの整合性を保ち、壊れることが無い。@ITを参考にして執筆した後述の文章を、自分なりに理解して書き直しました。FAT32などがある。Linuxでしかファイルシステムを使わない場合は、一番優れていて安心できるのはext4。Linuxのルートファイルシステム(Linuxのシステムをインストールするファイルシステム)にはext4を使うのが無難。Bツリーファイルシステムはまだまだ未熟である。LinuxでもWindowsでも読み書きできるようにファイルシステムをフォーマットしたい時はFAT形式がおすすめである。USBハードディスクなどを使う場合でも、WindowsからもLinuxからも読む場合はFAT形式を使おう。ジャーナリングext3やext4(現在のLinuxの標準)などのファイルシステムはジャーナリングファイルシステムと呼ばれ、ジャーナリングによってシステムの整合性を保つ機能が搭載されている。ジャーナリングに対応していないと、不意に異常終了した時にファイルシステムが破損する場合がある。VFSLinuxではVFSという機構を使うことで、各ファイルシステムの差異を吸収することが出来る。プログラマやプログラムは各ファイルシステムの実装の詳細を知らなくても、VFSのインターフェイスだけを使ってあらゆるファイルシステムに対応することができる。@IT関連ページファイルシステムの基本操作については、UNIX管理(4.ファイルシステム)を参照のこと。システムコール・APIを参照のこと。@ITを参考に執筆しました。iノードiノードは要するにディスクのインデックス。実際の記録媒体であるディスクやブロック、位置情報を持っている。iノードによってディスクの位置情報が一意に識別される。プロセスとファイルシステムiノードを操作するには、インターフェースとなるファイルオブジェクトによってディレクトリを管理するdentryオブジェクトが操作され、さらにiノードを管理する。そのような階層的に抽象化された仕組みで実現されている。read()などを発行し、カーネルに要求する。2.カーネルはシステムコールを受け付け、その要求に従ってファイルオブジェクトを作成する。それをファイルディスクリプタ(fd)に関連づける。3.ファイルオブジェクトはカーネルの操作によって、ディレクトリパス情報を持つdentryオブジェクトに関連づけられる。4.dentryオブジェクトはiノード(ディスクに具体的に結び付けられているビットマップ情報)に関連づけられる。5.新しいiノードが位置情報を得たら、ファイルオブジェクトをインターフェースとする、アドレス情報をポインタとしてプロセスに返す。プロセスは要求への返答として、ファイルディスクリプタという形で、ファイルオブジェクトへのポインタを得る。ファイルディスクリプタを通じて間接的にiノードを操作する。キャッシュとダーティビットiノードの要求に素早く応じることが出来るように、カーネルの内部ではオブジェクトをキャッシュしている。実際に書き込みや読み込みが行なわれた場合、このiノードに対して書き込みがなされたことを示すフラグ(ビットマップ)が記される。これを「ダーティビット」と呼ぶ。これが付けられたiノードは、書き込みがなされている(汚れた)バッファであり、ディスクに書き込まれるためのキュー(列)である汚れた(DIRTY)リストに繋がれる。カーネルは、効率化のためにこのようなキューをハッシュを先頭とした「双方向リスト」(前後の要素へのポインタを持つリストデータ構造)で管理している。キューはiノードの状態によってUSED(使用中)、UNSED(未使用)、DIRTY(書き込み中)の状態で別リストに繋がれる。DIRTYリストにつながれたデータは、バッファキャッシュとしてI/O待ちのI/Oリクエストキューに入れられる。ここに入れられたiノードは、順次対応するディスクブロックに書きこまれる。書き込みが終了したリストはUSED(使用中)に戻され、参照が終了したらUNSED(未使用)に入れられ、適当な時期に解放される。このようにiノードオブジェクトはVFS内の状態遷移で表すことができる。非同期処理アプリケーション側の書き込み操作は、実際にはカーネル内のキャッシュに対して行われる。ユーザーの書き込み要求に対してカーネルは、メモリに「書きこんだ」というビットフラグを立ててすぐにリターンを返す。この書き込み要求はキャッシュバッファに蓄えられて、updateデーモンが定期的にディスクに書き込む(フラッシュ)。カーネルの内部の処理としては、ビットのついたデータをDIRTYバッファとしてキャッシュに保存し、バックグラウンドでバスの転送速度に合わせてデータディスクに転送する。読み込み時は、ディスクから読み込むのは時間がかかるので、一度読み込んだものをキャッシュとして置いておき、そこから読み込む、という方法がとられる。sys_write()を呼び出す。これは、VFSの機能であるトランスレーションによって、ext2固有の関数に置き換えられる。ext2はキャッシュに溜まったデータを、固有の命令を使用して対応するブロックに転送する。転送が完了すると、割り込み命令が発行される。それによって起動されたドライバの低レベルなストラテジルーチンがディスクコントローラに適切な命令を発行し、I/Oリクエストキューにたまったデータを順次処理する。@ITを参考に執筆しました。FFS)を元に開発されたもので、UNIXで用いられてきた「ブロック管理アルゴリズム」をベースにしている。ブロックアルゴリズムはディスク領域を「ブロック」に分けて管理する方法である。ext2は、ファイルシステム作成時に、平均的なファイルサイズの予測に従ってブロックを作成し、複数のブロックを「ブロックグループ」にまとめて管理する。・ブートブロック・ブロックグループ0・ブロックグループ1・...(以降連続してブロックグループが並ぶ)・ブロックグループnとなる。ブートブロックはパーティションのブートセクタとして予約されているブロックであり、ブートローダなどを格納する。実際のデータの保持ext2では、ブロックグループ0のスーパーブロックの中に、パーティション内部のブロックグループ全体の管理情報が格納される。・使用されているブロックグループ・最終fsck時刻など、ファイルシステムに関係するさまざまな情報が含まれている。「グループディスクリプタ」は、「データブロックビットマップ」や「iノードビットマップ」情報などを参照して空きブロックや空きiノードを探し、データを割り当てる際に最適なブロックを決定するのに使われる。ext2関係の情報もっとext2/ext3/ext4について詳しく知りたい以下が参考になる。@ITを参考に執筆しました。ext2/ext3がベースとするブロックアルゴリズムは、ブロック数が対応するディスクのジオメトリ数に制限されること、ファイルサーチにO(n)かかること、ファイルサイズに関係するパフォーマンス低下など、いくつかの問題があった。これに対して、ReiserFS、JFS、XFSなどのファイルシステムでは、ブロックアルゴリズムの限界に対して、早い段階からデータベースの技術をファイルシステムに取り組んでいた。データベースの分野では、ファイルシステムとは比較にならないほど、大量のデータを素早く検索し、データの追加や変更も簡単に行えるような設計の研究が続けられてきた。ReiserFS、JFS、XFSでは「B-Tree」アルゴリズムが利用されている。「B*-Tree」や「B+-Tree」はその派生形である。B-Treeの仕組み以下のリンク先が参考になる。数学的なので、理解するのは難しい。Linuxのファイルシステム以外でもデータベースなどの分野で使われている木構造である。Qiita詳しくはSQL/RDBMSのページを参照のこと。ext4以外にも、以下のようなファイルシステムがある。7で標準のファイルシステムになった。12ではBtrfsが標準のファイルシステムに採用された。xfsBtrfsBtrfsは現在Linuxカーネルで開発されている先駆的なファイルシステム。機能が豊富で、まだ未熟だが進歩の期待度が大きい。いつか標準になる日が来るかもしれない。機能的には、SunのZFSに近い。ZFSはGPLとの兼ね合いでLinuxでは使えないため、Btrfsに期待が集まっている。そもそもはOracleによって開発された。Oracleは信頼できるデータベースの会社であるため、Oracleとさまざまな会社が協力することで、信頼性のあるファイルシステム技術に成長することを願っている。btrfsZFS最近はLinuxでもZFSを利用できる。ライセンス問題はなんとかして解決している模様。マイナビニュースリーナスはZFSが嫌いLinuxカーネル開発リーダーのリーナス・トーバルズは、ZFSを公式のLinuxカーネルにはマージしない姿勢を改めて強調している。ZFSを「バズワード」と明言し、起訴好きのOracleがGPLにライセンスでもしない限りはマージしないとのこと。これにより、ZFSを使いたいLinuxユーザーは、Ubuntuなどの独自に対応したディストリビューションを使うか、FreeBSDなどの他のUNIX互換OSを使う必要が改めて浮き彫りになった。