【问题标题】:System wide mutex in QtQt中的系统范围互斥锁
【发布时间】:2013-02-18 09:15:22
【问题描述】:

我有一个进程,我想检查它是否正在运行,并朝那个方向做出决定,即我想从另一个实例检查此应用程序的运行实例。

我可以运行 2 个应用程序实例,处理 2 种类型的数据。当第三个实例打开时,它需要检查其类型的另一个实例(来自已创建的 2 个类型)是否已经在运行。如果是这样,新的需要关闭并向其类型的已运行实例发送消息。

因此,我认为QtSingleApplication 将不起作用。

我希望创建一个系统范围的互斥体并以这种方式完成检查,但我在 Qt 中没有看到任何系统范围的互斥体。

还有QMutex,它只适用于应用程序的线程。

当我在线搜索时,还有一个叫做QSystemMutex的东西,但我想这是一个自定义解决方案?我没有在我的 Qt 安装或助手中找到它。

请问有什么方法可以使用 Qt 创建系统范围的互斥锁吗?

【问题讨论】:

  • 你知道为什么QtSingleApplication 不起作用吗??
  • 我可以运行 2 个应用程序实例,处理 2 种类型的数据。当第三个实例打开时,它需要检查其类型的另一个实例(来自已创建的 2 个类型)是否已经在运行。如果是这样,新的需要关闭并向其类型的已运行实例发送消息。在这种情况下,QtSingleApplication 根本不起作用。
  • 它应该可以工作。不是只需要根据类型给QtSingleApplication构造函数设置appId参数吗?
  • 更像这样。我有一个应用程序,它可以处理多种类型的数据。假设为 A 类型启动了一个应用程序实例。然后是 B 类型应用程序的一个实例。这是允许的。现在再次打开一个类型 A 的实例。它需要检查类型 A 的实例是否已经在运行,如果是,则将消息传递给它,然后关闭。这一切都不能用QtSIngleApplication 来管理。所以我想,当 A 类型启动时,创建一个 A 类型的系统范围的互斥锁和一个共享内存。如果另一个实例未能创建该互斥体,它将关闭。
  • 这正是QtSinglaApplication app("MyApp type A", argc, argv); if( app.isRunning() ) sendMessage("My Message"); 应该做的。为什么你如此确信它不会起作用?

标签: qt mutex


【解决方案1】:

互斥锁被定义为在一个进程中用作对象。您正在寻找流程之外的解决方案。

一个简单的解决方案是使用文件系统。创建一个文件并在进程停止时将其删除。当多个进程从不同的目录运行或应用程序崩溃时,这可能会更难。

更高级的解决方案是使用共享内存对象。这些对象存在于流程之外,可以从任何流程中检查和修改。可以在此处找到有关 QT 共享内存的示例:
http://doc.qt.digia.com/4.7-snapshot/ipc-sharedmemory.html

【讨论】:

  • 共享内存作为 IPC 机制很好。在确定特定类型的实例正在运行之后,我将使用它与正在运行的实例进行通信。我想创建一个具有特定名称的系统范围的互斥锁,然后让相同类型的另一个实例尝试创建相同的互斥锁。一旦它失败了,它就知道它类型的另一个实例正在运行,然后它可以附加到共享内存并进行通信并关闭。但我需要一个系统范围的互斥锁。
  • 任何可以跨进程工作的互斥体都需要 IPC 才能这样做。我用谷歌搜索了一些并找到了一个可以做到这一点的课程。它位于 QT 扩展库中。 docs.huihoo.com/qt/qtextended/4.4/qsystemmutex.html
  • 我确实看到了..我在原帖中提到过。但是,我担心它是什么类型的解决方案..是否是 Qt 的一部分,以及许可问题..
【解决方案2】:

QtSingleApplication 绝对可以做到这一点。如果应用程序已经在运行,则没有任何义务要求您终止。您可以在 QtSingleApplication 为您提供的基础上定义引导协议,即您将其 api 用作 锁定原语

您可以做的是将具有特定类型的消息发送到正在运行的实例,例如该类型的字符串表示。很简单:您向正在运行的实例发送一条消息,他会告诉您是否欢迎您。

  • 每次应用程序启动时,它都会监听消息(即使有一个正在运行)。如果类型与他的不同,他只能确认一条消息。
  • 如果没有应用程序在运行,他会直接开始工作。
  • 如果有应用程序正在运行,他会发送 hello 消息(例如他的类型)并等待 ACK、NACK 或超时。如果超时,您可以决定该怎么做。
  • 如果您在等待回复并收到 hello,则表示您拒绝。

ps:您所描述的并不完全是互斥锁。以下代码

int main(int argc, char **argv) {
   QtSingleApplication app(argc, argv);

   if (app.isRunning())
       return 0;
   //blah blah blah
}

已经是互斥体了。

【讨论】:

    最近更新 更多