Come condividere la memoria tra le applicazioni scritte in C / C ++

8

Sto seguendo un programma scritto in C / C ++ per il controllo in robotica. Fondamentalmente, tre diversi programmi vengono eseguiti contemporaneamente e comunicano tramite la memoria condivisa. Google-ling intorno a me trovato pensa come vxWorks e le librerie boost interprocess headers ( Boost documentation : Condivisione della memoria tra processi ).

Ora, non voglio guardare l'implementazione, posso leggere il link sopra. Ma non riesco a capire come funziona la libreria boost. Voglio dire, un'applicazione si occupa di allocare memoria e altri di accedere a quella memoria, ma come comunicano? non è pericoloso farlo?

    
posta cauchy 15.04.2015 - 12:22
fonte

5 risposte

9

But I cannot get my head around to how the boost library does this.

Il meccanismo interprocess di boost ha tre componenti necessari per funzionare:

  1. file mappato in memoria: un file mappato in memoria deve essere creato e passato ad un allocatore boost.interprocess. Questo allocatore prenderà blocchi del file e li userà come se fossero restituiti da uno std :: allocator, con mappatura applicata in modo che la memoria sia compatibile con la memoria specifica del processo.

  2. contenitore boost.interprocess; questo tipo di contenitore utilizzerà la memoria restituita dall'allocatore e offrirà un'interfaccia simile a std :: container (begin / end / size / push_back, ecc.).

  3. meccanismo di sincronizzazione; questo può essere qualsiasi mutex interprocesso e dovrebbe essere usato per prevenire condizioni di accesso ai dati.

I mean, one application allocates memory, and other access that memory, but how do they communicate? isn't it unsafe to do this?

La memoria allocata è in realtà un file mappato in memoria condiviso La comunicazione è indiretta, con entrambe le applicazioni che impostano o leggono i dati, a seconda delle necessità. La sicurezza deriva dall'uso delle primitive di sincronizzazione dell'interprocess.

    
risposta data 15.04.2015 - 14:10
fonte
5

la memoria condivisa non è l'immagine completa per IPC, è un meccanismo per il trasferimento dei dati ma è ancora necessario un modo per informare l'altro processo che alcuni dati sono stati aggiornati ed è disponibile per la lettura. Il modo in cui lo fai dipende da te, in genere utilizzi un mutex OS o un oggetto evento, ogni processo attende che venga impostato, la scrittura dell'applicazione lo imposta una volta terminata la scrittura. Quindi i thread negli altri programmi si attivano e leggono.

In alternativa puoi eseguire il polling, leggere regolarmente i dati per un valore che cambia quando i dati vengono aggiornati (ad esempio un contatore incrementale).

    
risposta data 15.04.2015 - 12:39
fonte
4

Boost utilizza la mappatura della memoria di un file.

Sia unix che windows supportano la creazione di file che non esistono sul file system normale proprio per questo scopo.

Quindi dovrai sincronizzare l'accesso a quella memoria come faresti se diversi thread dovessero accedervi. Il significato delle letture simultanee può avvenire senza sincronizzazione, ma non appena un processo vuole scrivere dovrai impedire agli altri di accedervi.

Le operazioni atomiche sulla memoria condivisa sono ancora possibili se si desidera una sincronizzazione senza blocco.

    
risposta data 15.04.2015 - 12:43
fonte
3

La memoria condivisa è ancora solo memoria. Puoi inserire un mutex, uno spinlock o qualsiasi altra primitiva di sincronizzazione e usarli per sincronizzare l'accesso dei tuoi processi alla memoria condivisa, esattamente come i thread usano quelle primitive per sincronizzare l'accesso alla memoria a loro visibile.

Le uniche differenze reali sono:

  1. I thread

    condividono tutta la memoria e lo stesso spazio di indirizzamento, quindi i puntatori grezzi funzionano per loro. La memoria condivisa tra i processi funziona esattamente allo stesso modo, ma può essere mappata a diversi indirizzi in ogni processo, quindi non puoi semplicemente passare i puntatori grezzi tra loro

    • NB. questo ha un effetto a catena su alcuni dettagli di implementazione di metodi virtuali, informazioni sul tipo di runtime e altri meccanismi C ++. Aderisci a tipi banali-inizializzabili (semplici vecchi dati) senza metodi virtuali o cast dinamici nella memoria condivisa, non usare caratteri tipografici su di essi, e dovresti stare bene.
  2. alcune primitive di sincronizzazione potrebbero richiedere flag o attributi speciali per funzionare correttamente tra i processi (vedere l'attributo PTHREAD_PROCESS_SHARED per i mutex del thread POSIX, ad esempio). Questo non ha a che fare con la memoria e la sincronizzazione in sé, ma a causa dell'interazione del kernel / schedulatore necessaria per svegliare i camerieri che dormono.

but how do they communicate?

Allo stesso modo, diversi thread comunicano, tenendo conto delle avvertenze sopra

isn't it unsafe to do this?

Sì, è altrettanto pericoloso che i processi comunichino tramite la memoria condivisa, così come i thread devono comunicare attraverso la memoria condivisa e hanno bisogno di una sincronizzazione equivalente (o identica) per renderlo sicuro.

    
risposta data 15.04.2015 - 12:41
fonte
3

Si noti che C e C ++ sono lingue diverse.

La memoria condivisa è impossibile solo in standard C11 o C ++ 11 (poiché lo standard non lo definisce), o anche C ++ 14 (di cui n3690 bozza, e presumibilmente standard ufficiale, non menziona la memoria condivisa al di fuori del multi-threading). Quindi hai bisogno di librerie aggiuntive per ottenere memoria condivisa. Ma alcuni sistemi operativi supportano la memoria condivisa. Esistono quindi numerose librerie che forniscono memoria condivisa, costruita sopra i servizi esistenti del sistema operativo. Potresti forse prendere in considerazione l'uso della POCO libreria del framework (che riassume i dettagli specifici del sistema operativo)

Per Linux (e forse POSIX), guarda shm_overview (7) . Dovrai sincronizzarti, quindi consulta anche sem_overview (7)

VXWorks (che non conosco, ma cercato su Google) ha VxMP

Devi capire attentamente cosa sta realmente accadendo. Probabilmente vorresti condividere solo vecchi vecchi dati struct -s (non classi C ++!) E dovresti fare molta attenzione agli indirizzi (ogni processo potrebbe ottenere un indirizzo diverso per il segmento di memoria condiviso comune) e alla sincronizzazione.

In alternativa, usa i thread. Si noti che lo standard C ++ 11 definisce una libreria di thread .

    
risposta data 15.04.2015 - 12:37
fonte

Leggi altre domande sui tag