1

在系统调用中使用共享内存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 上,我可以对共享段的地址执行以下操作:

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 上做到这一点?还是直接等效?

4

1 回答 1

-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实现的。见链接

于 2021-01-02T08:51:57.533 回答