【问题标题】:boost::interprocess sync mechanisms (mutex, condition) in shared memory between 32 & 64 bit programs on OSX在 OSX 上的 32 位和 64 位程序之间共享内存中的 boost::interprocess 同步机制(互斥量、条件)
【发布时间】:2017-06-06 03:24:38
【问题描述】:

OSX 10.11.6,提升 1.63.0

我有一个 64 位 ma​​ster 进程,它使用 32 位 slave 进程进行实时渲染(我没有特定 32位动态库,因此我无法将其重新编译为 64 位)。时间很关键,我发现 boost::interprocess 的共享内存实用程序运行良好,但我遇到了互操作性问题。一些进程间机制在编译 32 和 64 时大小不同,因此当 slave 从共享内存引用它们时会导致问题。

64 bit
Scoped Lock: 16
Condition: 48
Mutex: 64
Semaphore: 4

32 bit
Scoped Lock: 8
Condition: 28
Mutex: 44
Semaphore: 4

我深入研究了 boost::interprocess::interprocess_mutex 标头,发现了 _pthread_types.h 中声明的大小:

// pthread opaque structures
#if defined(__LP64__)
#define __PTHREAD_SIZE__        8176
#define __PTHREAD_ATTR_SIZE__       56
#define __PTHREAD_MUTEXATTR_SIZE__  8
#define __PTHREAD_MUTEX_SIZE__      56
#define __PTHREAD_CONDATTR_SIZE__   8
#define __PTHREAD_COND_SIZE__       40
#define __PTHREAD_ONCE_SIZE__       8
#define __PTHREAD_RWLOCK_SIZE__     192
#define __PTHREAD_RWLOCKATTR_SIZE__ 16
#else // !__LP64__
#define __PTHREAD_SIZE__        4088
#define __PTHREAD_ATTR_SIZE__       36
#define __PTHREAD_MUTEXATTR_SIZE__  8
#define __PTHREAD_MUTEX_SIZE__      40
#define __PTHREAD_CONDATTR_SIZE__   4
#define __PTHREAD_COND_SIZE__       24
#define __PTHREAD_ONCE_SIZE__       4
#define __PTHREAD_RWLOCK_SIZE__     124
#define __PTHREAD_RWLOCKATTR_SIZE__ 12
#endif // !__LP64__

struct _opaque_pthread_mutex_t {
    long __sig;
    char __opaque[__PTHREAD_MUTEX_SIZE__];
};

使用时

boost::interprocess::interprocess_mutex
boost::interprocess::interprocess_condition

两个程序都编译为 64 位,数据渲染效果非常好。

有没有办法强制尺寸一致?或者我忽略了不同的 IPC 机制?

使用条件的好处在于,它们可以在何时唤醒阻塞线程并大大减少浪费的 CPU 周期,因为等待线程/进程不必不断运行来检查值。是否有另一种方式以这种方式向线程/进程发出信号?

我知道在 OSX 上至少有几个程序在 64 位 32 位之间实现了非常快速和高效的数据渲染,所以答案肯定就在某个地方......

【问题讨论】:

  • 您可能已经检查过了,但只是为了确保:您是否验证过其他 ipc 机制对您来说太慢了?
  • 我使用了 boost::interprocess::interprocess_semaphore,因为它们只包含一个原子 uint32,但问题是两个线程都会浪费大量的循环等待值去下。我尝试过校准睡眠时间,但即便如此,我还是遇到了数据丢失//过载或过多未使用的 CPU 使用情况。我只是假设通过管道或套接字同步会太慢,但我也试一试!
  • 是的,管道、域套接字和/或 fifos 是我的想法。它们肯定比共享内存慢得多,因此它们可能不适合您,但它们在不同应用程序之间提供了相当强的解耦。根据您对数据的处理方式,它可能已经足够好了。遗憾的是,我在该领域的经验很少,所以如果有一个我不知道的简单解决方案,我不会感到惊讶。也许您可以对 boost 类型进行逆向工程并创建自己的便携式版本。

标签: c++ macos ipc shared-memory boost-interprocess


【解决方案1】:

所以我听取了 MikeMB 的建议,对管道进行了一些研究。我发现这篇论文http://ace.ucv.ro/sintes12/SINTES12_2005/SOFTWARE%20ENGINEERING/44.pdf 建议使用管道作为锁定机制。看起来对管道的读/写实现了与进程间条件变量相同的信号机制,因此线程阻塞/唤醒非常有效。

看起来读/写速度足够快,可以在我的机器上进行实时设置! (虽然还不能保证它可以在其他机器上运行,我只在我的 2011 MBP(2.2 GHz Intel Core i7)上测试过)

它似乎和条件一样有效,而且我还没有收到任何数据丢失。这是我做的。只需将其中一个放在共享内存中,ma​​sterslave 进程就可以相应地调用 wait() 和 post()。

struct PipeSemaphore
{
    PipeSemaphore()
    {
        // make sure semaphore will work in shared memory
        // between 32 <-> 64 bit processes
        static_assert (sizeof (int) == 4);

        int res = pipe (p);

        // pipe failed to open
        if (res == -1)
            assert (false);
    }

    ~PipeSemaphore()
    {
        close (p[0]);
        close (p[1]);
    }

    // if nothing is in the pipe stream,
    // the curr thread will block
    inline int wait() noexcept
    {
        char b;
        return read (p[0], &b, 1);
    }

    // writing to the pipe stream will notify
    // & wake blocked threads
    inline int post() noexcept
    {
        return write (p[1], "1", 1);
    }

private:
    int p[2];
};

对代码的任何建议将不胜感激!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-01-21
    • 2011-01-28
    • 2010-12-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多