GearsOSのメタ計算

  • 清水 隆博
    • 198584B
    • 河野研

研究目的

  • アプリケーションの信頼性を向上させたい
    • その為には土台となる OS 自体の信頼性が重要である
  • OSそのものも巨大なプログラム
  • 並列並行処理など起因するバグや、そもそもOSを構成する処理が巨大
    • テストコードで信頼性を保証しきれない
  • 形式手法を用いて信頼性を保証したい
    • モデル検査

ノーマルレベルとメタレベルを用いた信頼性の向上

  • プログラムの実行部分は以下の2つからなる
    • 入力と出力の関係を決める計算(ノーマルレベル)
    • プログラムを実行したり、 信頼性を保証するために必要な計算(メタレベル)
  • メタレベルの例
    • メモリやCPUの資源管理
    • システムコールの動作(副作用)
    • 並行実行(他のプロセスとの干渉)
    • モデル検査(可能な実行を列挙する方式の実行)
    • 証明(入力時と出力時の論理的な条件)、(invariant)
  • メタレベルの計算として信頼性を保証する

モデル検査

  • 実際に想定されるパターンを全て動かして検証する
  • デッドロック発生の検知
    • JavaPathFinderなど
  • 状態爆発が問題になる
  • Spinを用いる方法では、 promelaという言語で実装し直す必要がある

定理証明支援系

  • 論理学的なモデルに変更して証明する
    • Agda
    • Coq
  • HoareLogicを用いる
    • PreCondition -> Statement -> PostCondition
  • 従来の方法ではStatementには限られたコマンドしか使えない
    • ループは不変条件を使うが、 条件を見つけることが一般的には困難
    • 実装言語と同じ記述で証明をすることはできない

GearsOSでの信頼性の保証

  • メタレベルのみで信頼性の保証を行う
    • ノーマルレベルでの記述は変更しない
  • Continuation Based C(CbC)をつかって、ノーマルレベルとメタレベルの分離を行う
  • C言語の下位言語であり、 いくつかのCコンパイラ上で実装している
  • C言語の構文は使用可能だが、 関数呼び出しの他に軽量継続を持つ
    • 関数呼び出し時のスタックの操作を行わずjmp命令で次の処理に移動する
    • schemaなどと違い環境を持たず継続するために軽量継続と呼ぶ

GearsOSでの信頼性の保証

  • デフォルトのメタレベルの計算は自動生成される
  • 資源管理あるいは検証用のメタ計算は必要に応じて挿入する
  • これにより大きなコード変更が無くモデル検査や定理証明を行うことができる
  • モデル検査や定理証明の困難さはメタレベルのプログラミングとして吸収する
    • 例えばOSで使用するデータ構造に合わせたモデル検査用の状態圧縮
    • OSの検証に利用できるinvariantの提供
  • CbCを用いたOSであるGearsOSを開発している

CbCとCodeGear(ノーマルレベル)

  • 軽量継続で表現する単位をCodeGearと呼ぶ
  • CodeGearはCの関数とアセンブラの中間の様に使える
  • CodeGearは返り値の型の代わりに__codeで宣言する
__code cbc_read(__code (*next)(int ret)){
    struct file *f;
    int n;
    char *p;

    if(argfd(0, 0, &f) < 0 || argint(2, &n) < 0 || argptr(1, &p, n) < 0) {
        goto next(-1);
    }
    goto cbc_fileread(f, p, n, next);
}
  • cbcで書き直したxv6のreadシステムコールの例

CbCとCodeGear(メタレベル)

  • cbc_read_stub内で必要な引数をcontextから取り出す
    • 取得するものがなければノーマルレベルのCodeGearに継続する
__code cbc_read_stub(struct Context* cbc_context, enum Code next) {
        goto cbc_read(cbc_context, next);
}

cbcで書き直したシステムコールディスパッチの例

  • CbCはgoto文で呼び出す
    • 受け取ったシステムコール番号に対応するCodeGearに継続する
void syscall(void)
{
    int num;
    int ret;

    if((num >= NELEM(syscalls)) && (num <= NELEM(cbccodes)) && cbccodes[num]) {
        proc->cbc_arg.cbc_console_arg.num = num;
        goto (cbccodes[num])(cbc_ret);
    }

ノーマルレベルとメタレベルを用いた信頼性の向上

  • プログラムの実行部分は以下の2つからなる
    • 入力と出力の関係を決める計算(ノーマルレベル)
    • プログラムを実行したり、 信頼性を保証するために必要な計算(メタレベル)
  • メタレベルの例
    • メモリやCPUの資源管理
    • システムコールの動作(副作用)
    • 並行実行(他のプロセスとの干渉)
    • モデル検査(可能な実行を列挙する方式の実行)
    • 証明(入力時と出力時の論理的な条件)、(invariant)
  • メタレベルの計算として信頼性を保証する

モデル検査

  • 実際に想定されるパターンを全て動かして検証する
  • デッドロック発生の検知
    • JavaPathFinderなど
  • 状態爆発が問題になる
  • Spinを用いる方法では、 promelaという言語で実装し直す必要がある

定理証明支援系

  • 論理学的なモデルに変更して証明する
    • Agda
    • Coq
  • HoareLogicを用いる
    • PreCondition -> Statement -> PostCondition
  • 従来の方法ではStatementには限られたコマンドしか使えない
    • ループは不変条件を使うが、 条件を見つけることが一般的には困難
    • 実装言語と同じ記述で証明をすることはできない

GearsOSでの信頼性の保証

  • メタレベルのみで信頼性の保証を行う
    • ノーマルレベルでの記述は変更しない
  • Continuation Based C(CbC)をつかって、ノーマルレベルとメタレベルの分離を行う
  • C言語の下位言語であり、 いくつかのCコンパイラ上で実装している
  • C言語の構文は使用可能だが、 関数呼び出しの他に軽量継続を持つ
    • 関数呼び出し時のスタックの操作を行わずjmp命令で次の処理に移動する
    • schemaなどと違い環境を持たず継続するために軽量継続と呼ぶ

GearsOSでの信頼性の保証

  • デフォルトのメタレベルの計算は自動生成される
  • 資源管理あるいは検証用のメタ計算は必要に応じて挿入する
  • これにより大きなコード変更が無くモデル検査や定理証明を行うことができる
  • モデル検査や定理証明の困難さはメタレベルのプログラミングとして吸収する
    • 例えばOSで使用するデータ構造に合わせたモデル検査用の状態圧縮
    • OSの検証に利用できるinvariantの提供
  • CbCを用いたOSであるGearsOSを開発している

CbCとCodeGear(ノーマルレベル)

  • 軽量継続で表現する単位をCodeGearと呼ぶ
  • CodeGearはCの関数とアセンブラの中間の様に使える
  • CodeGearは返り値の型の代わりに__codeで宣言する
__code cbc_read(__code (*next)(int ret)){
    struct file *f;
    int n;
    char *p;

    if(argfd(0, 0, &f) < 0 || argint(2, &n) < 0 || argptr(1, &p, n) < 0) {
        goto next(-1);
    }
    goto cbc_fileread(f, p, n, next);
}
  • cbcで書き直したxv6のreadシステムコールの例

CbCとCodeGear(メタレベル)

  • cbc_read_stub内で必要な引数をcontextから取り出す
    • 取得するものがなければノーマルレベルのCodeGearに継続する
__code cbc_read_stub(struct Context* cbc_context, enum Code next) {
        goto cbc_read(cbc_context, next);
}

cbcで書き直したシステムコールディスパッチの例

  • CbCはgoto文で呼び出す
    • 受け取ったシステムコール番号に対応するCodeGearに継続する
void syscall(void)
{
    int num;
    int ret;

    if((num >= NELEM(syscalls)) && (num <= NELEM(cbccodes)) && cbccodes[num]) {
        proc->cbc_arg.cbc_console_arg.num = num;
        goto (cbccodes[num])(cbc_ret);
    }