进度标签用于定义正确性声明。进度标签表明在任何无限的系统执行中必须经常无限地访问带标签的全局状态的要求。验证者可以将任何违反此要求的行为报告为非进度周期。
和
Spin有一种特殊的模式来证明没有非进展周期。它使用预定义的LTL公式:
(<>[] np_)
将非进展正式化为标准的Buchi接受财产。
但是,让我们来看看非常原始的promela规范
bool initialised = 0;
init{
progress:
initialised++;
assert(initialised == 1);
}
根据我的理解,assert
应该成立,但验证失败,因为initialised++
只执行一次而progress
标签声称应该可以经常执行它。
然而,即使使用上述LTL公式,这也可以很好地验证ispin(见下文)。
如何正确测试语句是否可以任意执行(例如锁定方案)?
(Spin Version 6.4.7 - 2017年8月19日)
+ Partial Order Reduction
完整状态空间搜索:
never claim + (:np_:) assertion violations + (if within scope of claim) non-progress cycles + (fairness disabled) invalid end states - (disabled by never claim)
状态向量28字节,深度达到7,错误:0
6 states, stored (8 visited) 3 states, matched 11 transitions (= visited+matched) 0 atomic steps
哈希冲突:0(已解决)
内存使用情况统计(以兆字节为单位):
0.000 equivalent memory usage for states (stored*(State-vector + overhead)) 0.293 actual memory usage for states 64.000 memory used for hash table (-w24) 0.343 memory used for DFS stack (-m10000) 64.539 total actual memory usage
在init
中未获得(0 of 3 states)
pan:经过时间0.001秒
未发现错误 - 您是否验证了所有声明?
更新
仍不确定如何使用此...
bool initialised = 0;
init{
initialised = 1;
}
active [2] proctype reader()
{
assert(_pid >= 1);
(initialised == 1)
do
:: else ->
progress_reader:
assert(true);
od
}
active [2] proctype writer()
{
assert(_pid >= 1);
(initialised == 1)
do
:: else ->
(initialised == 0)
progress_writer:
assert(true);
od
}
让我们选择非进度周期的测试。然后ispin将其作为
运行spin -a test.pml
gcc -DMEMLIM=1024 -O2 -DXUSAFE -DNP -DNOCLAIM -w -o pan pan.c
./pan -m10000 -l
无误地验证。
所以让我们尝试使用ltl属性...
/*pid: 0 = init, 1-2 = reader, 3-4 = writer*/
ltl progress_reader1{ []<> reader[1]@progress_reader }
ltl progress_reader2{ []<> reader[2]@progress_reader }
ltl progress_writer1{ []<> writer[3]@progress_writer }
ltl progress_writer2{ []<> writer[4]@progress_writer }
bool initialised = 0;
init{
initialised = 1;
}
active [2] proctype reader()
{
assert(_pid >= 1);
(initialised == 1)
do
:: else ->
progress_reader:
assert(true);
od
}
active [2] proctype writer()
{
assert(_pid >= 1);
(initialised == 1)
do
:: else ->
(initialised == 0)
progress_writer:
assert(true);
od
}
现在,首先,
the model contains 4 never claims: progress_writer2, progress_writer1, progress_reader2, progress_reader1
only one claim is used in a verification run
choose which one with ./pan -a -N name (defaults to -N progress_reader1)
or use e.g.: spin -search -ltl progress_reader1 test.pml
好吧,我不在乎,我只想让它最终运行,所以让我们保持progress_writer1
并担心如何将它们拼凑起来:
/*pid: 0 = init, 1-2 = reader, 3-4 = writer*/
/*ltl progress_reader1{ []<> reader[1]@progress_reader }*/
/*ltl progress_reader2{ []<> reader[2]@progress_reader }*/
ltl progress_writer1{ []<> writer[3]@progress_writer }
/*ltl progress_writer2{ []<> writer[4]@progress_writer }*/
bool initialised = 0;
init{
initialised = 1;
}
active [2] proctype reader()
{
assert(_pid >= 1);
(initialised == 1)
do
:: else ->
progress_reader:
assert(true);
od
}
active [2] proctype writer()
{
assert(_pid >= 1);
(initialised == 1)
do
:: else ->
(initialised == 0)
progress_writer:
assert(true);
od
}
ispin用
运行spin -a test.pml
ltl progress_writer1: [] (<> ((writer[3]@progress_writer)))
gcc -DMEMLIM=1024 -O2 -DXUSAFE -DSAFETY -DNOCLAIM -w -o pan pan.c
./pan -m10000
哪个不会产生错误,而是报告
unreached in claim progress_writer1
_spin_nvr.tmp:3, state 5, "(!((writer[3]._p==progress_writer)))"
_spin_nvr.tmp:3, state 5, "(1)"
_spin_nvr.tmp:8, state 10, "(!((writer[3]._p==progress_writer)))"
_spin_nvr.tmp:10, state 13, "-end-"
(3 of 13 states)
是吗?灿烂!我完全不知道该怎么做。
如何让它运行?
答案 0 :(得分:1)
您的代码示例的问题在于没有任何无限的系统执行。
进度标签用于定义正确性声明。进步 label表示标记的全局状态必须是的要求 在任何无限的系统执行中经常无限地访问 。任何 验证者可以将违反此要求的行为报告为 非进展周期。
请尝试使用此示例:
short val = 0;
init {
do
:: val == 0 ->
val = 1;
// ...
val = 0;
:: else ->
progress:
// super-important progress state
printf("progress-state\n");
assert(val != 0);
od;
};
正常检查未发现任何错误:
~$ spin -search test.pml
(Spin Version 6.4.3 -- 16 December 2014)
+ Partial Order Reduction
Full statespace search for:
never claim - (none specified)
assertion violations +
cycle checks - (disabled by -DSAFETY)
invalid end states +
State-vector 12 byte, depth reached 2, errors: 0
3 states, stored
1 states, matched
4 transitions (= stored+matched)
0 atomic steps
hash conflicts: 0 (resolved)
Stats on memory usage (in Megabytes):
0.000 equivalent memory usage for states (stored*(State-vector + overhead))
0.292 actual memory usage for states
128.000 memory used for hash table (-w24)
0.534 memory used for DFS stack (-m10000)
128.730 total actual memory usage
unreached in init
test.pml:12, state 5, "printf('progress-state\n')"
test.pml:13, state 6, "assert((val!=0))"
test.pml:15, state 10, "-end-"
(3 of 10 states)
pan: elapsed time 0 seconds
然而,检查进度会产生错误:
~$ spin -search -l test.pml
pan:1: non-progress cycle (at depth 2)
pan: wrote test.pml.trail
(Spin Version 6.4.3 -- 16 December 2014)
Warning: Search not completed
+ Partial Order Reduction
Full statespace search for:
never claim + (:np_:)
assertion violations + (if within scope of claim)
non-progress cycles + (fairness disabled)
invalid end states - (disabled by never claim)
State-vector 20 byte, depth reached 7, errors: 1
4 states, stored
0 states, matched
4 transitions (= stored+matched)
0 atomic steps
hash conflicts: 0 (resolved)
Stats on memory usage (in Megabytes):
0.000 equivalent memory usage for states (stored*(State-vector + overhead))
0.292 actual memory usage for states
128.000 memory used for hash table (-w24)
0.534 memory used for DFS stack (-m10000)
128.730 total actual memory usage
pan: elapsed time 0 seconds
警告:确保在选项-l
之后写-search
,否则不会将其移交给验证者。
你问:
如何正确测试语句是否可以任意执行(例如锁定方案)?
简单地写一个活跃的财产:
ltl prop { [] <> proc[0]@label };
这会检查名为proc
且pid 0
的流程是否经常执行与label
对应的语句。
答案 1 :(得分:0)
由于您的编辑大幅改变了问题,我会写一个新答案以避免混淆。此答案仅解决 新内容。下次,考虑创建一个新的,单独的问题。
这是注意unreached in ...
警告信息非常重要的一种情况,因为它会影响验证过程的结果。
警告消息:
unreached in claim progress_writer1
_spin_nvr.tmp:3, state 5, "(!((writer[3]._p==progress_writer)))"
_spin_nvr.tmp:3, state 5, "(1)"
_spin_nvr.tmp:8, state 10, "(!((writer[3]._p==progress_writer)))"
_spin_nvr.tmp:10, state 13, "-end-"
(3 of 13 states)
与编译过程中创建的文件_spin_nvr.tmp
的内容有关:
...
never progress_writer1 { /* !([] (<> ((writer[3]@progress_writer)))) */
T0_init:
do
:: (! (((writer[3]@progress_writer)))) -> goto accept_S4 // state 5
:: (1) -> goto T0_init
od;
accept_S4:
do
:: (! (((writer[3]@progress_writer)))) -> goto accept_S4 // state 10
od;
} // state 13 '-end-'
...
粗略地说,您可以将此视为 Buchi Automaton 的规范,该规范接受writer
进程的执行,_pid
等于3
,其中progress_writer
它无法经常无限地到达标签ltl
的声明,即 ie它只有有限次数。
为了理解这一点,您应该知道,要验证φ
属性spin
,Promela
会构建一个自动机,其中包含原始φ
模型中不满足的所有路径φ
。这是通过计算自动机的同步产品来完成的,该自动机使用表示要验证的属性φ
的否定的自动机对原始系统进行建模。 在您的示例中,_spin_nvr.tmp
的否定由以上代码摘录自never progress_writer1
并标有Spin
。然后,φ
检查是否有可能执行此自动机:
φ
,并且此类执行跟踪是您的财产的见证(又名反例) active [2] proctype writer()
{
1: assert(_pid >= 1);
2: (initialised == 1)
3: do
4: :: else ->
5: (initialised == 0);
6: progress_writer:
7: assert(true);
8: od
}
。警告告诉您,在生成的同步产品中,无法访问这些状态。为什么会这样?
考虑一下:
2:
在第initialised == 1
行,您检查writer
。在2:
设置为initialised
之前,此语句强制1
阻止init
行。幸运的是,这是由5:
进程完成的。
在第initialised == 0
行,您检查writer
。在5:
设置为initialised
之前,此语句强制0
阻止initialised
行。但是,没有任何进程会在代码中的任何位置将0
设置为progress_writer:
。因此,标有(1) /* always executable */
(0) /* never executable */
skip /* always executable, same as (1) */
true /* always executable, same as skip */
false /* always blocks, same as (0) */
a == b /* executable only when a equals b */
的代码行实际上无法访问。
请参阅documentation:
<SELECT name="toAddress"> <option value="info">Info</option> <option value="general">General</option> </SELECT>
如果条件语句成立,则只能执行(传递)。 [...]