Linuxでkernelを再構築せず自分のシステムコールを追加(偽)する

最近、仮想記憶システムを勉強するためCR3レジストとページテーブルをアクセス必要がある。
Ring3でアクセスできないので、OSのカーネルにする。しかしどうするとカーネルに入れるのかなって。
ネットで検索して、Linuxで一番簡単な方法はカーネルモジュールを書く。しかしコード全部はカーネルモジュールで実行するのはいろいろな不便(デバッグとか)です。
CR3とページテーブルをアクセスするシステムコールがあれば便利だと思う。しかしこんなシステムコールがないようだ。ネットで自作システムコールの資料を参考して、カーネルの再構築は必要らしい。それは面倒くさい。
じゃあカーネルモジュールに自分のシステムコールを追加できるのかなって思って、よく見るとシステムコールの数はカーネルのソースコードで#defineで定義されちゃった。それは追加不可能になった。
ほかの方法はいろいろ探した。既存のシステムコールを入れ替えるのはいい方法に見える。
確かにネットでいろいろ関する資料があるが、中古なので今のカーネルに対してもう使えなくなった。だから私はこの記事を書いた。

まず、ネットでの資料によるとシステムコール関数のアドレスははsys_call_tableに保存される。このテーブルを編集すればシステムコールを入れ替える。でもそんな簡単ではない。1、今のカーネルは、sys_call_tableというシンボルは公開しない。だからカーネルモジュールのコードにextern void** sys_call_table;を書けば構築したカーネルモジュールはinsmodできない。sys_call_tableというシンボルは見付からないから。
実はこのシンボルのアドレスは、/boot/System.mapに探せる・・・
私のシステムに、
grep sys_call_table /boot/System.map-3.6.6-1.fc16.i686.PAE
を実行すれば
c097b2c0 R sys_call_table
って表れる。
これで、sys_call_tableを見付からない問題は解いた。

あと、sys_call_tableの編集の問題だ。sys_call_tableは読み出し専用なので、普通で編集できない。しかし今コードはカーネルで実行してるから、この「読み出し専用」は無視できる。
「読み出し専用」は、「書き込み不可」だ。この「不可」はCR0レジストの十六番目のビットに制御される。カーネルでCR0レジストを編集できる。だから「CR0の十六番目のビットを0になせる→sys_call_tableを編集する→CR0の十六番目のビットを戻らせる」って方法でsys_call_tableを編集できる。

って、勝手にsys_call_tableを編集すればシステムは正しく動かなくなった。だから自分の編集は元のシステムコールの機能に邪魔するのはいけない。私はgetpidを入れ替える。getpidは元々パラメータがない。自分の書いた偽者関数はパラメータを調べて、特定な値なら自分のコードを実行する。でないと元の関数を実行する。

最後、カーネルモジュールの構築。ネットで「GCCを直接に実行してカーネルモジュールを構築する」の記事が多い。私はその方法で失敗した。Makefileを使用するって説明する記事に従って成功した。詳しいのは知らないままで。

これはソースコードです。
http://www1.axfc.net/uploader/so/2682144.bz2

注意:CR3を取得のコードは絶対に間違った。ただいまカーネル仮想メモリアドレスとユーザー仮想メモリアドレスについて勉強している。

mygetpid.cは自作システムコールを試すコードです。Makefileに入らない。
直接コンパイルしていいです。