2009年11月10日火曜日

C++のスタートアップ(C++でカーネルコードを書きたい)

以前適当に解決しようとした問題を調べた。といってもwiki.osdev.orgのC++の項目を読んだだけ。英語の読解力がろくに無いので間違えて理解したかもしれない。

ようは、OSというパトロンがいなくなったC++さんが路頭に迷わないための手引き。

以下自分の理解をまとめる。osdev.orgにはサンプルコードまで載っていて素敵です。

デフォルトのスタートアップコードを利用しない

デフォルトでは、G++はmainが呼び出される前に実行されるコードや、mainがreturnした後に呼ばれるコードをリンクしようとする。

なので、無効にするために-nostartfilesオプションをつける。

new/delete

必要な処理を無効にしてしまった以上は、自前で実装しなければならない。とりあえず、global/staticなオブジェクトのコンストラクタ、デストラクタを呼び出すコードを追加すればよい。

コンストラクタ、デストラクタではnew/delete(new[]/delete[]も)が必要なので、これらも実装しなければならないが、その際にメモリマネジメントの機能が必要になる。特定のアドレスにオブジェクトを作るplacement newというテクニックもあるらしい。

mainの前後

GCC(G++)はctors、dtorsというセクションにそれぞれ、 global/staticオブジェクトのコンストラクタ、デストラクタを登録する。

C++のコードにジャンプする前後にこれらのセクションの内容を処理する。セクションの境界を知るためにリンカスクリプトを書く。

__cxa_atexitは、__cxa_finalizeで呼ばれる,オブジェクトや共有リソースを破棄する時のハンドルを登録する。

C++のカーネルコードが終了したら__cxa_finalize(0)を呼ぶべき。 dctorの処理と__cxa_finalize(0)の呼び出しは両方するべきなのだろうか。まぁ、終了時の事はあまり気にしなくても動くので良いか。

__dso_handleはさようならするオブジェクトがDynamic Shared Objectかどうか判別する?

純粋仮想関数(pure virtual function)

純粋仮想関数がオーバライドされていないのに呼びだされる(?)ときのための関数を用意する。

どこかの.cpp内に、__cxa_pure_virtualという関数を作る。なお、__cxa_pure_virtualにはextern "C"でC言語のリンケージを指定する。

Local static variables

GCCはローカルなスタティック変数のコンストラクタの前後に、複数スレッドから同時に呼び出されないように保護するコードを挿入するらしい。

いままで気にした事が無いシンボル名が出てきたので、他のどこかのオプションで無効になってるのではなかろうか。標準ライブラリを無効にするところだろうか。

標準ライブラリ

無効にするために-nostdlibオプションをつける。

実行時型情報

無効にするために-fno-tffiオプションをつける。

例外

無効にするために-fno-exceptionsオプションをつける。

0 件のコメント:

コメントを投稿