分割くん 裏話



分割くん誕生!!(1999/02/11、しなぷす)
 Safe Melt 32 Version 1.38には、分割くんという、ファイルを複数枚のフロッピーなどに分割しながら圧縮するソフトのβ版が添付されています。このソフトの開発のいきさつは次のようなものでした。
 それは、1998年の年末の話でした。海外で勤務しているCCBTeam Schaftの代表)が日本に帰ってくるというので、私しなぷすとKPJが会いに行った時のことです。Team Schaftの今後の活動方針やら、最近のパソコンのハードやソフトの話など、色々と話しているうちに、次のような話が出ました。

CCBSafe Meltってさ、大きなファイルをフロッピー何枚かに分割して記録できるようにできない?」
KPJ「ああ、僕もおんなじ事を考えてました。」
しなぷす「多分できると思うけど。」
CCBSafe Meltにその機能を付けてもいいし、別のプログラムにしてもいいけど。」
しなぷす「別のプログラムにする方が、ユーザーインターフェースの設計がやりやすいかなあ。」

 この会話がきっかけで、ファイルの圧縮・分割プログラムの開発が始まりました。
分割くん開発開始(1999/02/11、しなぷす)
 12月は仕事が忙しかったのですが、年末年始の休みはプログラム開発に時間を割けそうです。
 1999年は、プログラムを作って明けました。厳密にいうと、98年の大晦日にプログラムの開発を始めて、99年の三が日は、ほとんどプログラムに時間を使いました。
 大晦日と三が日の、都合4日間を使い、圧縮・分割プログラムの試作品ができました。Safe Melt 32をベースに作っているので、これだけの短時間でとりあえず動作するプログラムができたのでした。

 私はこのプログラムに、「分割くん」という仮称を付けました。これは、以前「Safe Meltって、どう読むんですか?」というメールをユーザーの方からいただいたので、「わかりやすい名前の方がいいかも」と思って付けた物です。
 後にTeam Schaftのメンバーにソフトの名称について相談したところ、CCBも「分割くん」という名称を候補の一つとして考えていたようで、「分割くん」を正式名称にすることに決まりました。分割くんのバージョン情報を見ると、「圧縮・分割自由自在 分割くん」と書いてありますが、「圧縮・分割自由自在」はYEWの発案です。
大きな落とし穴(1999/02/11、しなぷす)
 たった4日間で試作品ができたので、「なんだ、簡単じゃん」と思って、いい気分で1月4日から出勤したのですが、これは甘い考えでした。YEWがMOでの動作試験をしたところ、ディスクの読み取りエラーが発生することが分かりました。この原因を調べる内に、泥沼に足を突っ込んでしまったのでした。

 症状から、「問題はWindowsの仮想記憶の仕組みに関係ある可能性が高い」と直感し、仮想記憶の仕組みについて、WindowsのAPIのオンラインヘルプやら、家にあったWindowsのプログラムの本やら、図書館にあったWindowsの内部動作の解説書やらを調べている内に、不具合の原因が判明しました。

 アプリケーションなどからのメモリ要求によって物理メモリが不足してくると、Windowsはあまり使われていないメモリページをスワッピングファイルに待避してから解放しますが、プログラムのあるメモリ領域は、スワッピングファイルに待避せずにメモリを解放します。これは、スワッピングファイルに待避せずともEXEファイルから読み直せるからです。
 つまり、Windowsのアプリケーションプログラムは、原則的に動作中はいつでもディスクから読み出せるようになっている必要があります。しかし、分割圧縮したファイルを自己解凍すると、2枚目のディスク以降を処理している時は、自己解凍プログラムが読み出せない状態になったのです。

 この問題を解決するために、何冊かの本を読み、Windowsのメモリ管理の機構を調べました。
 その結果、VirtualQuery関数でプログラムのある仮想メモリ領域が取得できること、そしてVirtualLock関数で、仮想メモリ領域の一部を物理メモリにロックできることが分かりました。これでプログラム領域を物理メモリにロックしてしまえば、プログラムがディスクから読み出せなくても、元々メモリフォールトが起こらないため、問題が生じないはずでした。
 でも・・・・。
Windows95って・・・・(1999/02/11、しなぷす)
 「ディスクの読み取りエラー発生の問題」を解決するために、VirtualQuery関数とVirtualLock関数を使って分割くんを作り直し、「これで問題は解決した」と思ったのは、つかの間でした。Windows 95で動作試験をしたところ、やっぱりMOでファイルを分割すると、以前と同様の問題が生じます。

 「どうして?(T_T)」と思いながら、APIのオンラインヘルプをよく読み直してみると、VirtualLock関数の説明の最後の方に、次のような注意書きがありました。

On Windows 95, the VirtualLock function is implemented as a stub that has no effect and always returns TRUE.

 Windows 95には、VirtualLock関数があるものの、実際にはその関数は何の働きもしないのです。しかも、TRUE(関数は成功した)が返ってきます。思わず、「まともにメモリ管理をする気があるのか?Windows 95!」と叫びたくなりました。
 Windows 95では仮想メモリ空間を物理メモリにロックできないことが分かったので、その対策に3日間くらい悩みました。自己解凍型のファイル分割プログラムの開発をあきらめようかと思ったこともあります。

 しかし、ある時ふとアイデアが浮びました。あまり使われていないページから解放されるなら、プログラムの領域を常にアクセスし続ければいいはずです。そこで、VirtualQuery関数で取得したプログラム領域をアクセスし続ける裏スレッドを走らせておくという、裏技を思い付きました。初めて作るマルチスレッドプログラムが、このような裏技的なプログラムになるとは夢にも思っていませんでした。
テスト・テスト・テスト(1999/02/11、しなぷす)
 早速、裏スレッドを使う分割くんを作りました。その動作試験をせねばなりませんが、私はMOドライブを持っていません。それまでは、MOドライブを持っているYEWに試験を依頼したり、職場(大学の研究室)のMOドライブが空いている時に使わせてもらったりしていました。

 しかし、YEWは遠く離れた所に住んでいますので、パソコン通信だけが情報伝達の手段となります。対面で話できないため、あまり具体的に情報交換をすることができません。また、大学の研究室は、ちょうど修士論文の締め切りの時期なので、論文のバックアップ用にMOドライブがフル稼動しています。あまり学生たちに迷惑をかけるわけにはいきません。(その節はご迷惑をかけました>五條くん)そこで、思い切って分割くんの動作試験用にMOドライブを購入しました。(元が取れるほどドネーションが集まらないだろうなあ。)

#修士論文の締め切り前は、研究室が戦場のようになりますが、
#私自身も英文論文の書き直しの締め切りのために、戦場に突
#入しました。昼間は論文、夜はプログラミングの毎日でした。

 MOを購入してからは、CD−ROMを2、3枚のMOに分割して、それらをハードディスクに解凍してみる試験を何回もしました。ドライブを購入してから2、3日で10GバイトくらいはMOに書き込んだのではないでしょうか。
 さらに、OSに負荷をかけた状態で試験するために、画面いっぱいの大きさのJPEG画像を35枚開いた上にDelphiを立ちあげて、その裏で、圧縮・分割および解凍をする試験も行いました。常にハードディスクがガリガリいっていて、ウィンドウを1枚1枚描画している様子が観察できるような極限状態での試験ですが、無事、分割くんは機能しました。

 このようにして、分割くんの安定性がある程度確認できたため、今回β版として公開することになりました。当方ではフロッピーディスクと230MBのMOでしか動作確認をしていないため、他のメディアで圧縮・分割された方は、是非動作状況の報告をしなぷすまでお願いします。
 余談になりますが、Safe Melt 32を分割くんに書き換える過程で、Safe Melt 32のプログラムに効率の悪い書き方をしている点が何個所か見付かりました。Version 1.38へのバージョンアップは、これらの個所の書き直しがメインになっています。