SoftEther トップ
> SoftEther 開発日記
SoftEther 開発日記
カーネルモードのプログラムを書いてみる (2003年7月15日)
SoftEther を実現するためのコンポーネントとして、仮想 LAN カードと仮想 HUB がある。
仮想 HUB は普通のサービスとして実行されるように設計したので、普通の Socket
を利用したアプリケーションのように動作すればよい。したがって、ユーザーモードのコードのみで実現することができる。
仮想 LAN カードを実現するためには、どうやらカーネルモードのコードを書く必要があるようである。Linux とかでは tun
デバイスをうまく使えば、わざわざデバイスドライバを書かなくてもユーザーモードのみでうまく作れるという話を聞いているが、Windows では
tun デバイスというものがない。(※)
結局、仮想 LAN カードを作るために DDK を使用してカーネルモードのドライバを開発することは避けられないことがわかった。そこで
DDK を Redmond から購入すると共に、DDK 関係の書籍を何冊か購入。
これまでカーネルモードで動作するプログラムを書いた経験が無いので (Windows 用アプリはたくさん書いたが、どれもユーザーモード
Win32 を使ったものだった)、何から初めていいかわからない。DDK のサンプルを make してみたりしたが、よくわからない。
そもそもデバイスドライバの開発に Visual Studio を使うことはできないのだろうか。DDK
を使ってドライバをビルドするためには、DDK の提供するコンパイラとリンカ、ライブラリ
ファイルを使わないといけないようである。これはコマンドラインからやるとうまくいく。しかし、ある程度コード量が増えてきたら、Visual
Studio を使って開発をしたくなった。
Visual Studio を使ってデバイスドライバをビルドする方法は、Web サイトを探してもあまり載っていなかった。購入した DDK
の本でも、Makefile を書いて nmake する方法しか書いていない。そこで色々試して見ると、既存の LIBC
などをすべて無効にして、DDK のライブラリ ntdll.lib や ntoskrnl.lib、ndis.lib などをリンクするように
Visual Studio のプロジェクト オプションを設定すれば、Visual Studio で F7
キーを押すだけでビルドできるようになった。Visual Studio
のプロジェクト設定で「すべての既存のライブラリを無視」というのがあるが、こんな変なオプションが何のためにあるのだろうかと思っていたが、デバイスドライバの開発ではこれは必須である。
デバイスドライバはカーネルモードで実行される。これは Win32 API
をデバイスドライバ内で呼び出してはならないということを意味する。C の標準ライブラリ関数も呼び出してはならない。標準関数は内部的に API
を呼び出しているためである。たとえばメモリを確保したいときに malloc
などとしてはならないのである。カーネルモードのプログラムを書くのは意外と厄介であることがわかった。
しかも、デバッグがかなり難しい。ユーザーモードだと Win32 デバッガが使用できたが、カーネルモードではエラー
(メモリアクセス違反など) が発生すると一瞬で青画面になり、コンピュータを再起動しないといけなくなる。
この際に、カーネルメモリをダンプするような設定にしておくと、C:\Windows に Memory.dmp
というファイルができる。これを再起動完了後に windbg
などで読み込むと、停止した場所がわかる。こうやって、エラーのたびにコンピュータを再起動して開発を続けた。
最終的に SoftEther の Ver 0.30
ができるまで、カーネルモードでのクラッシュのために再起動した回数は、500回を越えたと思う。某氏曰く、コンピュータの再起動はマシンに負担がかかるので、VMware
のような仮想ソフトを使ったほうがいい、とのことだが、仮想ネットワークドライバを仮想マシンの中で開発すると訳がわからなくなりそうなのと、VMware
自体も仮想 NIC を持っているのでそういうのと競合してうまく動かなかったら嫌なので VMware
のようなものは導入しなかった。すべて実マシンで作業した。
※ 後になって、実は Microsoft Tun Adapter という謎のデバイスドライバが drivers.cab
に入っていることが判明。しかし使用方法は不明。MSDN
や海外サイトを探してもわからなかった。しかもこのドライバ、一度インストールするとアンインストールできないという変な特徴がある。危険。
戻る |