Linuxファイルシステムは、いかにしてディレクトリの内容を列挙するのか

ちょっと調査する必要に迫られまして。

まずはlsのソースコードから…… と思ったがlsのソースが見つからなかったのでやめ(しょぼい)

linuxのシステムコール/ライブラリルーチンをざっと眺めますと、opendir()というのが目に付きます。調べてみたところどうやらopendir,readdirで指定したディレクトリ内のファイルを列挙できる(参照)ということで、ここから追っていきましょう。

opendir,readdirのつかいかたですが、まずopendir()でDIRをゲット。それを引数にreaddir()を呼ぶたびに対象ディレクトリ内にあるファイルをdirent形式でひとつづつ返してくれます。

てきとーにぐぐってみると、opendir()の中身はopen()で、readdir()のほうではsys_getdentsでディレクトリエントリを取得しているもよう。

http://www.linux.or.jp/JM/html/LDP_man-pages/man2/getdents.2.html
これはあなたが興味を持つような関数ではないと言いながらちゃんと解説してあってしかも日本語訳までされているツンデレ感に萌えますね。

int getdents(unsigned int fd, struct dirent *dirp, unsigned int count);

こいつにopen()で取得したファイルデスクリプタを渡してやるとdirpになんか設定されると。
direntの中身はこんな。

struct dirent
{
    long d_ino;                 /* inode number */
    off_t d_off;                /* offset to next dirent */
    unsigned short d_reclen;    /* length of this dirent */
    char d_name [NAME_MAX+1];   /* filename (null-terminated) */
}

おっとここでinodeが登場。このへんを理解するために、Linuxファイルシステムを調べておこう。

http://www.linux.or.jp/JF/JFdocs/The-Linux-Kernel-10.html
linuxはいくつかのファイルシステムに対応している(ext2,vfat,iso9660,etc.)。これらを統一して扱うため、VFS(Virtual File System)というレイヤーがある。VFSアーキテクチャext2と似ていてinodeベースでファイルを管理する。inodeはファイルと一対一対応している。



で、getdentsを読んでみる。渡されたファイルデスクリプタからstruct fileをつくり、vfs_readdirを呼んでいるだけですね。


vfs_readdirでは、file->f_op->readdir()を呼んでいるだけのようですね。この先はファイルシステム依存、と。

えー、予想外の結果になってしまった。ファイル列挙はVFSのレイヤで完結してると思ってたのに……

とりあえずext2readdir()を追ってみましょう。
ギャー!いきなり難易度が上がった気がしますよ。とにかくこの階層が終着点であることは間違いなさそうなのですが(つづかない)

.netプログラムからrubyをつかう

rubydotnet
rubyから.netを使う機能のほうに力が入っているが、RubyInterpreter.dllっていうドトネトからrubyをevalったりできるライブラリもついてくる。

IRubyInterpreter i = RubyInterpreter.instance;
object resul=i.eval("1+1");

どれどれ……

ちょwwwww絶対パス指定wwwwww


はっきりいって使い物にならない出来なので自作することにしました。ちなみに現在個人的なプロジェクト(先日のHTMLパーサだのなんだの)を10個ほど抱え込んでおりことごとく未完成です。わはは。


ActiveScript RubyならCOMからrubyをつかえるぞ!ひゃっほう。COM操作なら.netの得意分野。


えーっ

よくわからんが、とりあえずVSの参照設定でRScript 1.0なるものを追加すればよさそう。なのだけどつかいかたがわからない。ActiveScript関係を調べなきゃいけないみたい。MSDNのこのへんか
……
……
……
FUCK
全く理解できなかった。


RubyCLRなんてものを発見したのでちょっと試すも動かず。ビルドには成功したのだけれど実行時にエラー(FileNotFoundException:指定されたモジュールが見つかりません。 (HRESULT からの例外: 0x8007007E))。なんか設定がいるんだろうけどドキュメント皆無・ソースにコメントすらなし・wikiつぶれてるという悪夢のような状況。MLは生きているようだが…… ううう。


(かきかけ)

カスタム属性を関数の戻り値に適用する方法

これ以外と知られてないと思いますよ!というか使う機会がほとんどないし。

class Hoge {
  [SomeAttr] //SomeAttrはHogehogeメソッドに適用される。では、メソッドの戻り値(string)に属性を適用するには?
  string Hogehoge() {}
}

MSDN:属性の対象 (C#)

class Hoge {
  [method: SomeAttr]
  [return: ReturnAttr] // ;)
  string Hogehoge() {}
}

ふー、びっくりした。

楽にunmanaged dllをダイナミックローディングしたい

http://www.codeproject.com/csharp/dynamicinvokedll.asp
ダイナミックローディングにはこんな方法があるよ、と。ここから妄想。

たとえば

interface IHoge {
   void Hage([MarshalAs(...)]string str);
   int Fuga(int,int);
}

なんてインタフェースだけ定義しておけば、あとは

IHoge hoge1=DynamicLoader.Load<IHoge>("hoge1.dll");

てな具合に呼んでやるだけで自動的に

class Hoge1 : IHoge{
   public void Hage(string str) {HageNative(str);}
   public int Fuga(int a,int b) {return FugaNative(a,b);}
   [DllImport("hoge1.dll",EntryPoint="Hage")]static void HageNative([MarshalAs(...)]string str);
   [DllImport("hoge1.dll",EntryPoint="Fuga")]static int FugaNative(int a,int b);
}

てなクラスを定義&そのインスタンスを返すような関数をつくることが可能なはずです。と思ってCodeDOMと少々格闘していたのですがかなりめんどくさそう(特にカスタム属性のあたりが)でコード生成までたどりつきませんでした。やれやれ。冷静に考えると、特にunmanaged dllをダイナミックローディングしたい理由もな…… いやあったよ!そもそもrubyのdll(コンパイル環境とかでファイル名まちまち)をなんとかしたかったんだった。でもだるいからファイル名きめうちでいくとおもう。