简体   繁体   English

c ++ 11进程间原子和互斥体

[英]c++11 interprocess atomics and mutexes

I have a Linux program which spawns several processes (fork) and communicates through POSIX Shared Memory.我有一个 Linux 程序,它产生多个进程(fork)并通过 POSIX 共享内存进行通信。 I'd like to have each process allocate an id (0-255).我想让每个进程分配一个 id (0-255)。 My intention is to place a bitvector in the shared memory region (initialized to zero) and atomically compare and swap a bit to allocate an id.我的目的是在共享内存区域(初始化为零)中放置一个位向量,并以原子方式比较和交换位以分配一个 id。

Is there a c++11-friendly way to do this?有没有一种对 c++11 友好的方法来做到这一点? Can I create an atomic bitset?我可以创建一个原子位集吗? Can I use a mutex across processes?我可以跨进程使用互斥锁吗? How do I assure that constructors get called once and only once across all processes?我如何确保构造函数在所有进程中仅被调用一次?

The C++11 threading primitives (mutexes, atomics, etc) are threading primitives. C++11 线程原语(互斥体、原子等)是线程原语。 The C++ standard doesn't reference processes, and most of these tools don't interoperate across processes. C++ 标准不引用进程,并且这些工具中的大多数不能跨进程互操作。

The only mention of processes in the standard is in a non-normative notation that says that lock-free atomics are intended to be OK for IPC :标准中唯一提到的进程是在一个非规范的符号中,它说无锁原子旨在适用于 IPC

Operations that are lock-free should also be address-free.无锁的操作也应该是无地址的。 That is, atomic operations on the same memory location via two different addresses will communicate atomically.也就是说,通过两个不同地址对同一内存位置的原子操作将进行原子通信。 The implementation should not depend on any per-process state.实现不应依赖于任何每个进程的状态。 This restriction enables communication by memory that is mapped into a process more than once and by memory that is shared between two processes.此限制允许通过多次映射到进程的内存和在两个进程之间共享的内存进行通信。

Outside of this non-normative notation, the threading primitives are not intended to be a means of achieving inter-process communication.除了这种非规范的表示法之外,线程原语并不打算成为实现进程间通信的一种手段。 The behavior of such objects when placed in shared memory (aside from lock-free atomics as noted above) is undefined.此类对象放置在共享内存中时的行为(除了如上所述的无锁原子)是未定义的。

You can use mutex inside of shared memory block, but the mutex must be declared as SHARED, therefore is not unusual using mutexes inside of share memory, u can make own class, it is very simple:您可以在共享内存块内使用互斥锁,但互斥锁必须声明为 SHARED,因此在共享内存内使用互斥锁并不罕见,您可以创建自己的类,非常简单:

class Mutex {
private:
    void *_handle;
public:
    Mutex(void *shmMemMutex,  bool recursive =false, );
    virtual ~Mutex();

    void lock();
    void unlock();
    bool tryLock();
};

Mutex::Mutex(void *shmMemMutex, bool recursive)
{
    _handle = shmMemMutex;
    pthread_mutexattr_t attr;
    ::pthread_mutexattr_init(&attr);
    ::pthread_mutexattr_setpshared(&attr, PTHREAD_PROCESS_SHARED);
    ::pthread_mutexattr_settype(&attr, recursive ? PTHREAD_MUTEX_RECURSIVE_NP : PTHREAD_MUTEX_FAST_NP);

    if (::pthread_mutex_init((pthread_mutex_t*)_handle, &attr) == -1) {
        ::free(_handle);
        throw ThreadException("Unable to create mutex");
    }
}
Mutex::~Mutex()
{
    ::pthread_mutex_destroy((pthread_mutex_t*)_handle);
}
void Mutex::lock()
{
    if (::pthread_mutex_lock((pthread_mutex_t*)_handle) != 0) {
        throw ThreadException("Unable to lock mutex");
    }
}
void Mutex::unlock()
{
    if (::pthread_mutex_unlock((pthread_mutex_t*)_handle) != 0) {
        throw ThreadException("Unable to unlock mutex");
    }
}
bool Mutex::tryLock()
{
    int tryResult = ::pthread_mutex_trylock((pthread_mutex_t*)_handle);
    if (tryResult != 0) {
        if (EBUSY == tryResult) return false;
        throw ThreadException("Unable to lock mutex");
    }
    return true;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM