如何在Promela中加入流程?

时间:2018-07-19 02:32:53

标签: multithreading spin promela

我正在用Promela制作模型,我需要等待2个过程结束才能继续。如何用Promela做到这一点?

1 个答案:

答案 0 :(得分:3)

首先:理论回顾。

在Promela中,进程 到达其代码末尾即结束,即

active proctype example() 
{
    /* some code */

    /* here it ends */
}

进程结束后,就可以被系统终止了。被终止意味着以下事情:

  • 该流程使用的_pid已释放,现在可以由以后实例化的任何其他 new 流程重新使用。
  • 该进程使用的任何资源都将被释放和释放

但是,请注意在进程终止时存在一些约束

  • 仅当进程p_i处于结束状态且没有其他进程p_j且其_pid的值大于p_i的值时才终止它还活着。

换句话说,只能按照创建过程的相反顺序终止进程,如docs所示。

此限制很重要,因为在Spin中,在任何给定时刻最多只能有255个进程同时处于活动状态。用run生成大量进程的任何尝试都会被阻止,除非与此同时一些现有进程已正确终止以为新进程腾出空间。


第二:加入。

现在,要实现join操作,我们首先必须确定这样做的意义:

  1. join应该在另一个进程执行到某个end state时捕获。
  2. join应该捕获到另一个进程有效终止并由系统释放其资源的时间

示例:案例1)

第一种情况绝对易于设计和实现。我们只需在进程之间使用某种 synchronization 机制,以通知已达到给定的end state

这可以通过多种方式完成,具体取决于您要建模的行为风格的种类。这是一个可能的实现:

mtype = { END };

proctype do_something(chan out)
{
    printf("proc[%d]: doing something ...\n", _pid);

end:
    out!_pid, END;
}

init {
    chan in = [5] of { mtype };
    pid pids[5];
    byte idx;

    /* atomic{} is optional here */
    atomic {
        for (idx: 0 .. 4) {
            pids[idx] = run do_something(in);
        }

        printf("init: initialized all processes ...\n");
    }

    /* join section */

    for (idx: 0 .. 4) {
        in??eval(pids[idx]), END;

        printf("init: joined process %d ... \n", pids[idx]);
    }
}

示例:案例2)

第二种情况的建模有点复杂,并且,据我所知,它可能有一些局限性,在某些设计下并不完全可行。

此方法依赖于变量_nr_pr的值,该变量是一个预定义的全局只读变量,用于记录当前正在运行的进程数。

一个可以:

A。逐一加入我们以相反的创建顺序生成的所有过程

proctype do_something()
{
    printf("proc[%d]: doing something ...\n", _pid);

end:
    /* nothing to do */
}

init {
    pid pids[5];
    byte idx;

    /* atomic{} is optional here */
    atomic {
        for (idx: 0 .. 4) {
            pids[idx] = run do_something();
        }

        printf("init: initialized all processes ...\n");
    }

    /* join section */

    for (idx: 0 .. 4) {
        (_nr_pr <= pids[4 - idx]);

        printf("init: joined process %d ... \n", pids[4 - idx]);
    }
}

B 。加入我们一次生成的所有进程

proctype do_something()
{
    printf("proc[%d]: doing something ...\n", _pid);

end:
    /* nothing to do */
}

init {
    pid pids[5];
    byte idx;

    /* atomic{} is optional here */
    atomic {
        for (idx: 0 .. 4) {
            pids[idx] = run do_something();
        }

        printf("init: initialized all processes ...\n");
    }

    /* join section */

    (_nr_pr <= pids[0]);

    printf("init: all children terminated ... \n");
}