Variabile globale in una libreria condivisa Linux

3

Supponiamo di avere la seguente configurazione sotto Linux, la libreria .so denominata "libcnt.so" e 3 app per lo spazio utente: "app1", "app2", "app3". Questa libreria fa una cosa semplice, dice all'app (l'app collega dinamicamente la libreria al runtime) di quante app è già collegata. Le app devono avere accesso al contatore dei link. Le mie conoscenze in C e Linux sono alquanto limitate in questo aspetto, ma poiché capisco queste informazioni dovrebbero essere archiviate in una variabile globale all'interno dell'oggetto condiviso. Qualcosa come:

in libcnt.h extern int cnt_loads;

in libcnt.c int cnt_loads = 0; // dove ogni collegamento incrementa questo contatore

o qualcosa di simile ...

Quindi, la mia domanda è come dovrebbe essere dichiarato e / o definito all'interno della libreria .so per garantire che più app dallo spazio utente ottengano la stessa istanza di quel contatore variabile?

    
posta user3730495 11.06.2014 - 16:52
fonte

1 risposta

7

In generale, la posizione della memoria mutevole non sarà condivisa tra le applicazioni se non esplicitamente richiesta. Pertanto, quando libcnt scrive su cnt_loads , la pagina in cui cnt_loads risiede sarà duplicata. Questo comportamento è noto come copy-on-write (COW). La stessa cosa accade se hai duplicato un processo con fork() : il processo figlio non condividerà la memoria scrivibile con il genitore, se una qualsiasi scrittura avviene nella pagina "biforcuta", la pagina verrà duplicata.

Se si desidera utilizzare la memoria condivisa per la comunicazione tra processi, è necessario utilizzare memoria condivisa SystemV , POSIX memoria condivisa o mmap invece. Nota che questi metodi sono piuttosto persistenti, cioè dovrai rimuovere l'oggetto memoria condivisa dopo l'uso.

È possibile approssimare il comportamento originariamente desiderato utilizzando la memoria condivisa definendo __attribute__((constructor)) e __attribute__((destructor)) funzioni per la libreria condivisa. La funzione constructor viene eseguita ogni volta che si apre la libreria, quindi è possibile utilizzarla per inizializzare / aprire la memoria condivisa e incrementare il conteggio del carico. Se mantieni anche un conteggio dei riferimenti (quante volte la libreria condivisa è aperta nel sistema adesso ) con destructor --- oltre al conteggio del carico ---, puoi correttamente rimuovere la memoria condivisa quando il conteggio dei riferimenti scende a 0.

Si noti che l'uso della memoria condivisa per le comunicazioni tra processi richiede assolutamente qualche forma di mutua esclusione , ad esempio un semaforo o mutex. La mancata sincronizzazione corretta porterà a condizioni di gara (ad esempio, cosa succede quando due processi aprono la tua libreria esattamente nello stesso momento?). Puoi evitare l'esclusione reciproca se puoi incrementare / decrementare i contatori in un modo atomico . Vi raccomando di usare semafori inter-processo forniti dal sistema operativo anziché atomici, perché le operazioni atomiche sono difficili da utilizzare correttamente e il vostro problema non è affatto critico per le prestazioni (quindi non è necessario eseguire operazioni di blocco).

    
risposta data 11.06.2014 - 17:10
fonte

Leggi altre domande sui tag