我需要实现一种阻塞等待方法,以实现在64位和32位进程之间进行同步。 使用对共享内存变量的忙等待会引入性能/调度问题,而POSIX信号量似乎不支持32位和64位进程之间的IPC。在Linux上是否有其他低开销的进程间同步替代方法?
Linux有futexes,它们是内核原语,提供了一种让一个进程休眠并让另一个进程唤醒它的方法。如果将它们用作互斥锁,则具有极好的快速路径(在这些情况下避免了内核调用),这很重要,但如果将它们用作信号量,则不太重要。
你只需要它的两个最原始的函数。其中一个FUTEX_WAIT,只有在共享内存中的特定条目具有特定值时,才会使内核休眠。另一个函数FUTEX_WAKE,唤醒使用FUTEX_WAIT进入休眠状态的进程。
你的“等待”代码会原子地检查共享变量以查看是否需要休眠,然后调用FUTEX_WAIT进入休眠状态,仅当共享变量未更改时。你的“唤醒”代码将更改原子共享变量的值,然后调用FUTEX_WAKE来唤醒任何处于休眠状态的线程。
如果您使用64位共享变量但仅在前32位中放置有意义的数据,则32位/64位问题将完全无关紧要,因此无论是寻址为64位变量还是32位变量,它都可以正常工作。
对于使用阻塞等待进行进程间同步,简单的解决方案包括命名管道(fd)或System V 信号量。
命名管道与文件路径相关联,因此两个进程可以独立打开该文件(一个用于读取,另一个用于写入)。对于纯同步,只需putc()
发信号,getc()
等待,每次一个字符(值无关紧要)。这创建了一个单向(“半双工”)通道;对于双向信号/等待,您需要创建两个文件。您甚至可以通过进行多个putc()
调用来排队多个信号,有点像永远不会饱和的信号量。
System V 信号量也与文件路径相关联。 这些表现类似于Dijkstra信号量。
有关其他选项,请查看
std::atomic<uint32_t>
或类似的方法来解决问题。不要使用比这更复杂的东西,例如std::mutex
,因为无法保证其在32位和64位代码之间兼容。对于简单的用例,简单的文件锁定方法也可能有效。 - Sam Varshavchikstd::atomic
之类的选项可以使用。至于文件锁定,实际磁盘I/O的机会相当小,因为所有操作将在缓冲内存中执行。编写一个循环来重写同一个文件,包含几个字节一千次。看看实际产生了多少磁盘活动。 - Sam Varshavchik