Windows 上的 WaitOnAddress() 在 Linux 上的完全等价物是啥?

Posted

技术标签:

【中文标题】Windows 上的 WaitOnAddress() 在 Linux 上的完全等价物是啥?【英文标题】:What s the Windows exact equivalent of WaitOnAddress() on Linux?Windows 上的 WaitOnAddress() 在 Linux 上的完全等价物是什么? 【发布时间】:2020-12-11 19:20:07 【问题描述】:

shmget() 系统调用中使用共享内存,我的 C++ 程序的目的是通过一个用 Rust 编写的服务器从 Internet 获取投标价格,这样每次价值变化时,我都在执行金融交易.

服务器伪代码

Shared_struct.price = new_price

客户端伪代码

Infinite_loop_label:
     Wait until memory address pointed by Shared_struct.price changes.
     Launch_transaction(Shared_struct.price*1.13)
Goto Infinite_loop

由于发起交易涉及支付交易费用,我只想在每次购买价格变化时创建一次交易。

使用信号量或futex,我可以做相反的事情,我的意思是等待一个变量达到一个特定的值,但是如何等到一个变量不再等于当前值?

而在 Windows 上,我可以在共享段的地址上执行 something like this:

ULONG g_TargetValue; // global, accessible to all process
ULONG CapturedValue;
ULONG UndesiredValue;

UndesiredValue = 0;
CapturedValue = g_TargetValue;
while (CapturedValue == UndesiredValue) 
      WaitOnAddress(&g_TargetValue, &UndesiredValue, sizeof(ULONG), INFINITE);
      CapturedValue = g_TargetValue;

有没有办法在 Linux 上做到这一点?还是直接等效?

【问题讨论】:

当然可以修改服务器的源代码。目标是在拍卖中始终成为最高出价者。 让服务器在更新值时触发信号量,然后等待该信号量而不是值本身 @thatotherguy 还没有(我的目标是修改服务器)。问题在于,当服务器立即再次锁定信号量时,客户端不会为相同的事务参数循环多次?而如果它等待变量本身,它将立即再次锁定,直到新值再次更改。 为什么您的客户端会循环多次而不是等待下一个信号? @thatotherguy 你的意思是客户端应该等待接收信号吗?我正在使用共享内存进行延迟(这是一场保持最高出价的竞赛,直到拍卖在 10 秒内结束),我担心保存和恢复上下文需要时间。还涉及内部变量,如果在执行新事务时向进程发出信号怎么办? 【参考方案1】:

您可以使用 futex。 (我假设“var”在 shm mem 中)

/* 客户端 */

int prv;

while (1) 
  int prv = var;
  int ret = futex(&var, FUTEX_WAIT, prv, NULL, NULL, 0);
  /* Spurious wake-up */
  if (!ret && var == prv) continue;
  doTransaction();

/* 服务器 */

int prv = NOT_CACHED;
while(1) 
  var = updateVar();
  if (var != prv || prv = NOT_CACHED)
    futex(&var, FUTEX_WAKE, 1, NULL, NULL, 0);
  prv = var;

需要服务器端调用 futex 来通知客户端。

请注意,WaitOnAddress 也是如此。

根据 MSDN:

同一进程中的任何线程如果更改了线程正在等待的地址处的值,则应调用 WakeByAddressSingle 来唤醒单个等待线程,或调用 WakeByAddressAll 来唤醒所有等待线程。

(添加)

对于这个问题,更高级的同步方法是使用条件变量。 它也是基于futex实现的。 见link

【讨论】:

这不是等价的。就我而言,问题是价值是未知的,因为它来自网络上的竞争对手。这就是我需要对任何价值变化采取行动的原因。 如果我们缓存之前的值并使得 1) 服务器只在值被修改时调用 FUTEX_WAKE 并且 2) 客户端调用 FUTEX_WAIT 来获取之前的值,那么客户端只有在值被修改时才能唤醒真的变了。我相应地修改了我的答案。 此外,您需要保护共享变量。 除了服务器端的语言不支持全局变量/符号并且多个线程可能会更新它。共享变量可能会更改且不受保护的事实是故意的。 好的,那么客户可能会错过一些价格更新:c。无论如何,当您希望在地址的值发生更改时收到通知(就像我回答的那样)时,可以使用 futex。

以上是关于Windows 上的 WaitOnAddress() 在 Linux 上的完全等价物是啥?的主要内容,如果未能解决你的问题,请参考以下文章

Windows Server 2012 R2 上的 Windows 服务 PlatformNotSupportedException 上的 WCF

Windows 10上的IE 11 VS 10上的Windows 11

WINDOWS“任务栏”上的内容为

在Windows 上的 Python

如何从 Windows 10 上的容器连接到 docker 主机(Docker for Windows)

为啥 Windows 上的 IE/Chrome 不支持端口 27977 上的 SOCKS5 代理? [关闭]