如何在没有超时/死锁的情况下在PROMELA进程中发送和接收?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何在没有超时/死锁的情况下在PROMELA进程中发送和接收?相关的知识,希望对你有一定的参考价值。

我无法解决这个PROMELA问题:我有N个进程(“pc”),它们可以通过一个通道发送和接收消息(“to_pc”)。每个进程都有自己的通道,通过它接收消息。对于能够接收的进程,我必须将其保持在循环中,该循环检查通道中的传入消息。作为第二个循环选项,该过程向所有其他通道发送消息。

但是,在模拟模式下,这总是会导致超时,而根本不会发送任何内容。到目前为止,我的理论是,我创建了一个死锁,所有进程都想立即发送,导致所有进程都无法接收(因为它们被卡在代码的“发送”部分)。

到目前为止,我一直无法解决这个问题。我试图使用全局变量作为信号量来“禁止”发送,因此只有一个频道可以发送。但是,这并没有改变结果。我唯一的另一个想法是使用超时作为发送的触发器,但这对我来说似乎不对。

有任何想法吗?提前致谢!

#define N 4

mtype={request,reply}

typedef message {
    mtype type;
    byte target;
    byte sender;
};

chan to_pc[N] = [0] of {message}

inline send() {
    byte j = 0;
    for (j : 0 .. N-1) {
        if
        :: j != address ->
            to_pc[j]!msg;
        :: else;
        fi
    }
}

active [N] proctype pc(){
    byte address = _pid;
    message msg;

    do
    :: to_pc[address]?msg -> /* Here I am receiving a message. */
        if
        ::msg.type == request->
            if
            :: msg.target == address ->
                d_step {
                    msg.target = msg.sender
                    msg.sender = address;
                    msg.type = reply;
                }
                send();
            :: else
            fi
        :: msg.type == reply;
        :: else;
        fi
    :: /* Here I want to send a message! */
        d_step {
            msg.target = (address + 1) % N;
            msg.sender = address;
            msg.type = request;
        }
        send();
    od
};
答案

如果你愿意,我可以编写一个完整的源代码工作版本,但也许它足以突出你正在处理的问题的来源,并让你有乐趣解决它。


分支规则

  • 任何具有可执行条件的分支都可以非确定性地进行
  • 如果没有具有可执行条件的分支,则采用else分支
  • 如果没有具有可执行条件的分支且没有其他分支,则该过程将挂起,直到其中一个条件变为真

考虑一下

1: if
2:    :: in?stuff -> ...
3:    :: out!stuff -> ...
4: fi

其中inout都是同步通道(大小是0)。

然后

  • 如果有人发送in的另一端,那么in?stuff是可执行的,否则它不是
  • 如果有人在out的另一端接收,那么out!stuff是可执行的,否则它不是
  • 该过程在1:行阻塞,直到两个条件中的至少一个可执行为止。

将该代码与此进行比较

1: if
2:    :: true -> in?stuff; ...
3:    :: true -> out!stuff; ...
4: fi

其中inout再次是同步通道(大小是0)。

然后

  • 两个分支都有可执行条件(true
  • 通过非确定性地选择在2:3:行执行分支,该过程立即承诺发送或接收某些内容
  • 如果进程选择2:然后阻塞,如果in?stuff不可执行,即使out!stuff可执行
  • 如果进程选择3:然后阻塞,如果out!stuff不可执行,即使in!stuff可执行

您的代码属于后一种情况,因为d_step { }中的所有指令都是executable,并且您的进程承诺过早发送。


总结一下:为了修复你的模型,你应该重构你的代码,以便始终可以从发送模式跳转到接收模式,反之亦然。提示:摆脱内联代码,将实际发送的决定分开。

以上是关于如何在没有超时/死锁的情况下在PROMELA进程中发送和接收?的主要内容,如果未能解决你的问题,请参考以下文章

如何在没有超时的情况下在 Travis CI 上安装一些东西?

事务 ( 进程 ID 60) 与另一个进程被死锁在锁资源上,并且已被选作死锁牺牲品。请重新运行 该事务。

SQL 过程超时

如何在没有 root 访问权限的情况下在服务器上杀死其他人的 Python 进程?

如何在不复制的情况下在多个进程中使用大型数据集?

Node.JS:不保持进程运行的 setTimeout