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