2012-10-31 15 views
14

Ho un programma Linux che genera diversi processi (fork) e comunica tramite POSIX Shared Memory. Mi piacerebbe che ogni processo allocasse un id (0-255). La mia intenzione è di posizionare un bitvector nell'area di memoria condivisa (inizializzato a zero) e confrontare e scambiare atomicamente un bit per allocare un id.C++ 11 atomica e mutui interprocess

Esiste un modo C++ 11 per farlo? Posso creare un bitset atomico? Posso usare un mutex tra i processi? Come posso assicurare che i costruttori vengano richiamati una sola volta e una sola volta in tutti i processi?

+0

fork restituisce un pid di processo figlio ai processori padre, perché non utilizzarlo solo anziché generarne un altro? Oppure sto fraintendendo la tua domanda –

+0

@aleguna Perché vorrei un valore compreso tra 0-255 e quando un processo lascia questo programma dovrebbe liberare il suo ID da riutilizzare. – dschatz

+0

@dschatz: "* Perché vorrei un valore compreso tra 0-255 *" Questo non spiega * perché * è necessario. Soprattutto quando il meccanismo PID è tanto * migliore *. –

risposta

11

C++ 11 primitive di filettatura (mutex, atomica, ecc.) Sono threading primitive. Non sanno nulla dei processi e non sono un mezzo per raggiungere la comunicazione tra processi.

Poiché lo standard C++ 11 non menziona i processi o la comunicazione tra processi, il comportamento di tali primitivi quando viene inserito nella memoria condivisa dal processo (un file mappato in memoria, una sorta di out-of-process globalmente memoria mappata, ecc.) non è definito.

+8

[atomics.lockfree] include "[Nota: le operazioni che sono prive di lock dovrebbero anche essere prive di indirizzi, ovvero le operazioni atomiche nella stessa posizione di memoria tramite due indirizzi diversi comunicheranno in modo atomico. -processo stato Questa restrizione consente la comunicazione da parte della memoria mappata in un processo più di una volta e dalla memoria condivisa tra due processi. - nota finale "" –

+0

Caro @Nicol Bolas, la tua risposta è ottima, ma non riesco a trovarla o tutti i libri che scrivono su questo argomento, quindi ho ancora dei dubbi sull'uso del mutex C++ 11 nella memoria condivisa.(come so, il mutex pthread è ok se si usa PTHREAD_PROCESS_SHARED) –

4

È possibile utilizzare mutex all'interno del blocco di memoria condivisa, ma il mutex deve essere dichiarato come condiviso, pertanto, non è insolito usando mutex all'interno della memoria azione, u può fare propria classe, è molto semplice:

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; 
}