トップ «前の日記(2008-09-30 [Tuesday]) 最新 次の日記(2008-11-07 [Friday])» 編集

Catra's Diary

2005|01|02|03|05|06|07|10|
2006|05|07|09|10|11|
2007|06|07|08|
2008|01|02|07|09|11|12|
2009|06|
2010|03|07|
2011|01|
2013|05|

2008-11-06 [Thursday]

_ SPIN による検証

spin によるモデル検証。 ただしここでは、モデルを記述するための言語 PROMELA ではなく、検証ツール spin のコマンドライン引数に重点をおいて記述。

最小構成

最小の PROMELA コードは以下のようになる。

/* ex01.pml */
init {
  skip;
}

このコードを検証する spin コマンド呼び出しは以下のようになる。

spin ex01.pml

現在のバージョンで実行すると画面に表示される結果は、

1 process created

で終わり。このコードに対して指定できるオプションとしては -v と -p がある。-v を指定すると、

Starting :init: with pid 0
  1:    proc  0 (:init:) line   2 "ex01.pml" (state 1)  [(1)]
1 process created

と少し詳細な情報が表示される。-p を指定すると、

Starting :init: with pid 0
  0:    proc  - (:root:) creates proc  0 (:init:)
  1:    proc  0 (:init:) line   2 "ex01.pml" (state 1)  [(1)]
  1:    proc  0 (:init:)       terminates
1 process created

とさらに詳しい情報が表示される。

プロセスの生成

プロセスを生成するコードは以下のようになる。proctype でプロセスの動作を記述し、run で起動する。

/* ex02.pml */
proctype A() {
  skip;
}

proctype B() {
  skip;
}

init {
  run A();
  run B();
}

最小構成と比較して指定できるコマンドライン引数が増えるわけではないので、ここはスルー。

グローバル変数とローカル変数

プロセスは、各プロセスが共有するグローバル変数と、宣言したプロセス内でのみアクセスできるローカル変数を利用できる。

/* ex03.pml */
byte turn = 0;

proctype A() {
  byte a;
  a = turn;
  turn = a + 1;
}

proctype B() {
  byte b;
  b = turn + 1;
  turn = b;
}

init {
  run A();
  run B()
}

最小構成から使える -v はここでも指定できるが、さらに -g や -l を指定することで、グローバル変数やローカル変数を 合わせて表示することができる。-v を指定したとき、

spin -v ex03.pml

例えば以下のように表示される。

Starting :init: with pid 0
Starting A with pid 1
  1:    proc  0 (:init:) line  17 "ex03.pml" (state 1)  [(run A())]
Starting B with pid 2
  2:    proc  0 (:init:) line  18 "ex03.pml" (state 2)  [(run B())]
  3:    proc  2 (B) line  12 "ex03.pml" (state 1)       [b = (turn+1)]
  4:    proc  2 (B) line  13 "ex03.pml" (state 2)       [turn = b]
  5:    proc  1 (A) line   6 "ex03.pml" (state 1)       [a = turn]
  6:    proc  1 (A) line   7 "ex03.pml" (state 2)       [turn = (a+1)]
3 processes created

ここで、 -g を合わせて指定すると、

spin -v -g ex03.pml

以下のように、グローバル変数である turn の内容がステップごとに表示される。

Starting :init: with pid 0
Starting A with pid 1
  1:    proc  0 (:init:) line  17 "ex03.pml" (state 1)  [(run A())]
                turn = 0
Starting B with pid 2
  2:    proc  0 (:init:) line  18 "ex03.pml" (state 2)  [(run B())]
                turn = 0
  3:    proc  1 (A) line   6 "ex03.pml" (state 1)       [a = turn]
                turn = 0
  4:    proc  1 (A) line   7 "ex03.pml" (state 2)       [turn = (a+1)]
                turn = 1
  5:    proc  2 (B) line  12 "ex03.pml" (state 1)       [b = (turn+1)]
                turn = 1
  6:    proc  2 (B) line  13 "ex03.pml" (state 2)       [turn = b]
                turn = 2
3 processes created

また、-l を合わせて指定した場合は以下のように、各プロセスのローカル変数が表示される。

Starting :init: with pid 0
Starting A with pid 1
  1:    proc  0 (:init:) line  17 "ex03.pml" (state 1)  [(run A())]
Starting B with pid 2
  2:    proc  0 (:init:) line  18 "ex03.pml" (state 2)  [(run B())]
  3:    proc  2 (B) line  12 "ex03.pml" (state 1)       [b = (turn+1)]
                B(2):b = 1
  4:    proc  2 (B) line  13 "ex03.pml" (state 2)       [turn = b]
                B(2):b = 1
  5:    proc  1 (A) line   6 "ex03.pml" (state 1)       [a = turn]
                A(1):a = 1
  6:    proc  1 (A) line   7 "ex03.pml" (state 2)       [turn = (a+1)]
                A(1):a = 1
3 processes created

両方 (-l -g) 指定した場合は、両方を表示する。

複数の状態を取るコードを検証する

上の例のように spin をそのまま実行した場合、プロセスの実行順序によって複数の状態を取りうるコードの場合は、 spin の実行ごとにどれか一つの状態遷移を行い、その内容を表示する。 取りうる状態を対話的に選択していく方法として -i が用意されており、 動作を確認しながら、という時には有効であるが、本来の目的であるモデル検証を行う場合には表示される情報量が多すぎ、 全状態を確認するために複数回実行するのは効率が悪い。

コードが取りうるすべての状態を検証するために spin は、PROMELA コードを C コードに変換してコンパイルし、 ネイティブアプリとして実行する形で実行速度を確保している。 そしてモデル検証を自動的に行うため PROMELA コードには状態を確認する命令を置き、 あらかじめ指定した条件に適合しない状態になった場合をエラーとして通知して、後から解析する形としている。

PROMELA コードを C コードに変換してコンパイルし、実行するには、以下のコマンドを順に実行する。

spin -a ex03.pml
gcc -o pan pan.c
./pan

結果は以下のように表示される。

hint: this search is more efficient if pan.c is compiled -DSAFETY

(Spin Version 5.1.6 -- 9 May 2008)
        + Partial Order Reduction

Full statespace search for:
        never claim             - (none specified)
        assertion violations    +
        acceptance   cycles     - (not selected)
        invalid end states      +

State-vector 12 byte, depth reached 2, errors: 0
        3 states, stored
        0 states, matched
        3 transitions (= stored+matched)
        0 atomic steps
hash conflicts:         0 (resolved)

    2.501       memory usage (Mbyte)

unreached in proctype :init:
        (0 of 2 states)

pan: elapsed time 0 seconds

ここで、pan.c をコンパイルする場合にマクロ定義で動作を変更する方法と、 コンパイラで生成されたコマンド ( pan ) に渡すコマンドライン引数、 さらに pan コマンド実行中に検出したエラーを解析するために使用する spin コマンドのコマンドライン引数と、 説明を続けるつもりだったが、今日はここまで。


トップ «前の日記(2008-09-30 [Tuesday]) 最新 次の日記(2008-11-07 [Friday])» 編集