OSECPUのQ&A
毎度のQ&A形式による説明
- (1) 仮想CPU関係
- (1-1) どうしてレジスタが64本もあるの?多すぎじゃないですか?
- x86の32bitモードは8本しかないですし、他のプロセッサでも16本程度のものが多いので、確かにこれは多く見えます。その疑問はもっともです。
- でもOSECPUでは、メモリへのアクセスはいろいろとセキュリティのためのチェックを伴うので、遅いのです。そうなるとできるだけレジスタだけで処理をしたいという気分になります。だからレジスタを増やしました。
- 一方で、レジスタを256本とかにしてもたぶんそんなに使いきれず、結局将来タスクスイッチ(コンテキストスイッチ)のオーバーヘッドが増えるだけになりそうなのでやめました。
- それにOSECPUの命令では、演算命令や比較命令で定数を指定することができません。「1を足す」とか「0と比較する」みたいなことができず、他のレジスタに事前に定数を代入しておいて、そのレジスタとの比較にしなければいけないのです。こんな仕様なのでレジスタは多そうに見えて実はそんなに多くないかもしれません。
- どうしてそんな命令の仕様なのかと言えば、それはJITコンパイラを単純化するためです。
- (1-2) どうしてレジスタマシンを採用したのですか?JIT前提のバイトコードって、スタックマシンが多いと思うんですが。
- うーん、まあ、作者の趣味・・・かなあ。もしあなたがスタックマシンを好きなのでしたら、それでOSECPUみたいなOSを構成してみたら面白いかもしれないですね!
- (1-3) どうしてポインタに対してはこんなに厳しいチェックがあるのに、整数値については無頓着なの?0x7fffffffに1を足したら負の数になってしまうけど、これは明らかにおかしいよね?
- 確かに明らかにおかしいです。しかし整数演算までチェックを厳しくするとさすがに速度が落ちてきそうで心配です。それに計算の結果おかしな値になっていたとしても、それは計算をさかのぼることで原因を突き止められる場合が多いです。しかし一方、ポインタがおかしくなった場合は悲惨です。オブジェクトがあらぬ値で上書きされて、もう何が何だかわかりません。ということで、ポインタのチェックは省略しません。
- 整数値については、想定している上限と下限だけをチェックすればいいかというとそうではない場合もあります。5の倍数しかありえないとか、1桁かもしくは5桁の数字になることが期待されているとか、その変域もかなり変則的です。そうであれば、自動のチェックはあまり役に立たないかもしれないので、CPUとしてはチェック機構を持ちません。しかしプログラマはそれらのルールをちゃんと反映してチェックしてください。そしてチェックコードを適切なアサートレベルのブロックに入れておいてください。これで翻訳時にどこまで反映させるかを選択することができます。
- (2) アクセス制限関係
- (2-1) OSECPUのアプリって、システムからメモリがもらえないって聞いたんですが本当ですか!?信じられません!
- APIで、メモリくださーいって言うことはできません。こう考えてください。あなたは今からお使いに行きます。その時にお金を渡されます。だからその範囲で買ってきてください。十分に買えるはずです。無制限に使えるクレジットカードは渡しません。これがOSECPUのリソース管理の考え方です。
- アプリは起動時に引数でリソースを受け取ります。足りなくなっても誰も助けてくれません。また、自分の子分(ライブラリ)を使う場合には、あなたが持っているリソースを切り分けて渡します。子分だってリソースがなければ生きていけませんからね。
- 現在の、好きなだけmallocできてしまうプログラミングスタイルは、明らかにクレジットカードを渡す方法です。メモリを食いつぶそうという悪意あるプログラムがいたらどうなりますか?みんな巻き込まれてしまいますよね?信用できない相手にクレジットカードを渡しますか?OSECPUは下請けの外部プログラムを基本的に信用しないのです。リソースは先払いで渡しますから、その範囲内でやってください。1000円で1500円の物を買ってこいとか、そんなことを言っているわけじゃないです。問題なくできるはずです。自分で自分のメモリの管理ができないような人は、OSECPUでは生きていけません。
- (2-2) もらったメモリを超えて使うことはできないんですか?
- できません。やろうとしたら強制停止させられます。だから続行できません。
- (2-3) 子分は私のメモリを自由にアクセスできてしまうのですか?OSはアクセス制限によってアプリから自己を守っているようですが、アプリはアクセス保護によってライブラリ関数のバグから自己を守ることはできないのでしょうか?
- できます。任意のポインタにアクセス域を設定できます。ただし、これは自分が持っているアクセス域よりも広くすることはできません。同じか小さくすることしかできません。これにより、ライブラリのバグから自己を守れます。
- (2-4) OSは追加のメモリをくれないだけではなく、時間に制約があるって本当ですか?
- 正確には時間ではなく、実行可能な命令数です。だから無限ループになったり、もしくはあまりにものろのろとやっていると、何の悪事を試みていなくても、勝手に止められてしまいます。時間ではないのでマルチタスクになっても動作可能量に影響はありません。PCの性能差があっても影響をうけません。・・・これもメモリと同じように、起動時に与えられていますし、ライブラリを使うのならライブラリにも分けてあげなければいけません。
- (2-5) ディスクにも制約はありますか?
- あります。ディスクというかファイルシステムですね。まずパスはルートから記述することができません。OSが渡したカレントディレクトリに対する相対パスだけです。しかも親をたどることができません。さらに容量制限もかかっています。ライブラリにパスを渡すことができますが、その場合はライブラリも同じ制約を受けます。つまり、アクセス域は下位に行くにつれてどんどん小さくなっていくのです。
- (2-6) ライブラリが上記のいずれかの制約を守れずに停止させられてしまったら、呼び出し元であるアプリも停止させられてしまうの?
- 何も設定してなければそうなってしまいますが、もし適切なハンドラを登録しておけば、子分が引き起こしたエラーでアプリが停止しないで済むようにできます。これはもともとはプラグインの暴走から本体アプリを守るためのものです。しかしこのハンドラは自分より下位のものにしか有効ではありません。自分自身のエラーをハンドルすることはできません。
- (2-7) OSは基本的にすべてのアクセス権を持っているわけですよね?じゃあAPIをうまく使ってだませばいいのかな?
- OSはアプリよりは広いアクセス権を持っているかもしれませんが、すべてではないと思います。OS自身もそれを切り分けてアプリを呼び出しているわけです。それで、OSをだます作戦についてですが、OSECPUにはカーネルモードとかスーパーバイザーモードがあるわけではなく、つまりは常にアクセス制限を受けています。言い方を変えればアプリもOSと同じモードで動いています。・・・あなたはシステムコールに際して、不当に広域なポインタをパラメータに書かなければ、OSに悪事を代行させることができません。でも、そのような広域なポインタをどうやって作るのですか?というかそれができるのなら、わざわざOSを使わずとも目的は達せられるのではないですか?
- モードがない(モードの切り替えがない)ということは、モードを切り替えるためのパスワードみたいなものも必要ないということです。rootパスワードとかそういうものはOSECPUとは無縁です。・・・OSは特権を有し、非常時にはアプリにもその特権を与えられるような仕組みしたUNIXだからこそ、典型的な攻撃が成立していたのです。
こめんと欄
- このページにこめんと欄はありません。このページの内容にコメントしたいときはimpressionsにお願いします。