Desidero aggiungere il controllo di rete di una manciata di parametri utilizzati da un servizio (daemon) in esecuzione su un sistema embedded Linux. Non c'è bisogno di chiamate di procedura, ogni parametro può essere interrogato in modo molto naturale. La memoria condivisa sembra un buon modo per mantenere il codice di rete fuori dal demone e limitare l'accesso condiviso a un insieme di variabili attentamente controllato.È C++ 11 atomico <T> utilizzabile con mmap?
Poiché non desidero che le scritture parziali causino la visibilità dei valori mai scritti, stavo pensando di utilizzare std::atomic<bool>
e std::atomic<int>
. Tuttavia, sono preoccupato che std::atomic<T>
possa essere implementato in un modo che funziona solo con i thread C++ 11 e non con più processi (potenzialmente, nemmeno con i thread del sistema operativo). In particolare, se l'implementazione utilizza qualsiasi struttura di dati memorizzata al di fuori del blocco di memoria condivisa, in uno scenario multi-processo ciò fallirebbe.
Vedo alcuni requisiti che suggeriscono di essere che std::atomic
non terrà un oggetto di blocco incorporato o puntatore ai dati aggiuntivi:
Le specializzazioni integrali atomici e la specializzazione
atomic<bool>
avrà layout standard. Ognuno di essi ha un banale costruttore di default e un distruttore banale. Ognuno di essi supporterà la sintassi di inizializzazione aggregata.Ci devono essere specializzazioni parziale del puntatore del modello di classe atomica. Queste specializzazioni devono avere layout standard, banali costruttori predefiniti e banali distruttori. Ognuno di essi supporterà la sintassi di inizializzazione aggregata.
Trivial costruzione e distruzione predefinite mi sembrano escludere i dati associati all'oggetto, memorizzati nell'oggetto, tramite una variabile membro puntatore o tramite un mapping esterno.
Tuttavia, non vedo nulla che escluda un'implementazione dall'utilizzo di una singola sezione mutex/critica globale (o anche una raccolta globale, purché gli elementi della raccolta non siano associati a singoli oggetti atomici - qualcosa sulla falsariga di è possibile utilizzare uno schema di associazione della cache per ridurre i falsi conflitti). Ovviamente, l'accesso da più processi non riuscirebbe su un'implementazione usando un mutex globale, perché gli utenti avrebbero mutex indipendenti e non si sincronizzerebbero effettivamente l'uno con l'altro.
È un'implementazione di atomic<T>
autorizzata a fare cose che sono incompatibili con la memoria condivisa tra processi, o ci sono altre regole che lo rendono sicuro?
Ho appena notato che la costruzione di default banale lascia l'oggetto in uno stato di non-ready, è richiesta una chiamata a atomic_init
. E lo standard menziona l'inizializzazione delle serrature. Se questi sono memorizzati all'interno dell'oggetto (e l'allocazione della memoria dinamica sembra impossibile, poiché il distruttore rimane banale), saranno condivisi tra i processi. Ma sono ancora preoccupato per la possibilità di un mutex globale.
In ogni caso, garantire una singola chiamata a atomic_init
per ciascuna variabile in un'area condivisa sembra difficile ... quindi suppongo che dovrò allontanarmi dai tipi atomici di C++ 11.
Come un addendum, [persone sono state raccomandando l'uso di operazioni atomiche con memoria condivisa] (http://stackoverflow.com/questions/4668592/ipc-via-mmaped-file-should-atomics-and- o-volatile-be-used), sebbene non sia chiaro se intendessero includere o escludere 'std :: atomic' o se altre API sono garantite per funzionare. –
Mi aspetto che un sistema ragionevole non utilizzi strutture dati esterne per le variabili 'atomiche'; in primo luogo sconfiggerebbe il punto atomico ... – Mehrdad
@Mehrdad: Non vedo come prendere una serratura globale possa vanificare lo scopo più che prendere una serratura locale, e lo Standard parla in modo specifico di implementazioni che fanno quest'ultima. –