Caricare documenti e articoli online 
INFtub.com è un sito progettato per cercare i documenti in vari tipi di file e il caricamento di articoli online.


 
Non ricordi la password?  ››  Iscriviti gratis
 

Memoria condivisa - Allocazione di un segmento di memoria condivisa - shmget ( )

informatica



Memoria condivisa

Nei sistemi Unix ogni processo possiede il relativo spazio di indirizzi virtuale e il sistema garantisce che un processo non acceda all'area di memoria corrispondente ad un altro processo. Con la memoria virtuale si dichiara una sezione di memoria comune a più processi che ogni processo può scrivere e modificare: a questo punto sarà necessario sincronizzare l'accesso di ogni singolo processo in quest'area.




Allocazione di un segmento di memoria condivisa - shmget ( )

Per allocare un segmento di memoria condivisa (operazione necessaria per poter usare il segmento), si impiega la shmget(): essa ottiene la chiave del segmento , la dimensione del segmento, i flag relativi ai permessi d'accesso sul segmento e relativi alla creazione della pagina qualora questa non esista. Il valore di ritorno è un ID che verrà usato dai processi per accedere al segmento.


//variabile usata per memorizzare il valore di ritorno della shmget (l'ID del segmento condiviso)
int shm_id;

// allocazione di un segmento avente dimensione 2048 bytes accessibile solo dall'utente corrente
shm_id = shmget(100, 2048, IPC_CREAT | IPC_EXCL | 0600);
if (shm_id == -1)

Se più processi cercano di allocare un segmento usando lo stesso ID (ogni processo esegue la shmget) ognuno di questi otterrà un ID per accedere alla stessa pagina a meno che come flag in shmget venga definito IPC_EXCL. In questo caso la chiamata avrà successo solo se la pagina non esisteva in precedenza.


Accesso ad unsegmento di memoria condivisa

Una volta allocata la pagina di memoria è necessario aggiungerla nella memory page dei processi. Questo procedimento è fattibile usando la shmat ( ): essa usa il parametro 'shm_id' che contiene l'ID ritornato dalla shmget ( ).


// specificare dove aggiungere la pagina
char* shm_addr;
char* shm_addr_ro;

// inserimento della pagina in una generica posizione libera
shm_addr = shmat(shm_id, NULL, 0);
if (!shm_addr)

// inserimento della pagina con possibilità di sola lettura per tutti i processi. Qualora un processo voglia
// scrivere in questa zona verrà generato un segnale d'errore (SIGSEGV) signal
shm_addr_ro = shmat(shm_id, NULL, SHM_RDONLY);
if (!shm_addr_ro)

Aggiunta di dati nella memoria condivisa

Aggiungere le informazioni in un segmento di memoria condivisa è fattibile usando la shmat ( ). Il segmento potrà contenere qualsiasi tipo di informazione fatta eccezione per i puntatori (dal momento che essi contengono indirizzi virtuali). Sebbene lo stesso segmento possa essere puntato da diversi indirizzi virtuali in ogni processo, ogni puntatore deve riferire a un'area di memoria puntata da un altro processo. Il seguente è un esempio relativo all'aggiunta dei dati in un segmento di memoria condivisa con successiva lettura. Si assume che 'shm_addr' è una strnga contenente l'indirizzo ritornato da shmat ( ).

// struttura utile per memorizzare le informazioni che verranno messe nel segmento

struct country ;


// definizione della variabile * define a countries array variable.

int* countries_num;

struct country* countries;


// creazione di un indice per i paesi sul segmento condiviso

countries_num = (int*) shm_addr;

*countries_num = 0;

countries = (struct country*) ((void*)shm_addr+sizeof(int));


strcpy(countries[0].capital_city, "U.S.A");

strcpy(countries[0].capital_city, "Washington");

strcpy(countries[0].currency, "U.S. Dollar");

countries[0].population = 250000000;

(*countries_num)++;


strcpy(countries[1].capital_city, "Israel");

strcpy(countries[1].capital_city, "Jerusalem");

strcpy(countries[1].currency, "New Israeli Shekel");

countries[1].population = 6000000;

(*countries_num)++;


strcpy(countries[1].capital_city, "France");

strcpy(countries[1].capital_city, "Paris");

strcpy(countries[1].currency, "Frank");

countries[1].population = 60000000;

(*countries_num)++;


// stampa a video le informazioni di tutti i paesi

for (i=0; i < (*countries_num); i++)


Uso della malloc: sebbene la memoria è stata già allocata (shmget) non c'è bisogno di usare la malloc per inserire i dati nel segmento. E' buona norma dimensionare il segmento affinché esso possa contenere quantità di dati sempre crescenti (senza usare la realloc, ma pre-dimensionandolo).

La memoria è allineata (lo si suppone).

Completezza del modello dei dati: è necessario aggoungere tutti i dati, evitando di tralascarne qualcuno, nel segmento di memoria  condivisa onde evitare che altri processi accedano apparentemente piena ma di fatto vuota.


Distruggere un segmento di memoria condivisa

E' possibile distruggere il segmento di memoria condivisa, a meno che qualche processo non lo stia usando, qualora questi non servisse. Nell'esempio di seguito il segmento verrà distrutto solo dopo che tutti I processi lo avranno rilasciato.


// struttura usata dalla system call shmctl()
struct shmid_ds shm_desc;

// distruzione del segmento di memoria condivisa
if (shmctl(shm_id, IPC_RMID, &shm_desc) == -1)

Qualsiasi processo è in grado di distruggere il segmento di memoria condivisa, a patto che questi possa scrivere nel segmento, e non solo quello che l'ha creato.


Esempio

Il file "shared-mem.c" mostra come il singolo processo utilizzi la memoria condivisa: naturalmente qualora due o più processi utilizzassero lo stesso segmento di memoria condivisa, si verificherà una "race condition" (un processo modifica il segmento mentre un secondo processo sta leggendo lo stesso segmento). Onde evitare questa situazione si utilizzeranno dei meccanismi di bloccaggio (SysV semafori con la mutua esclusione).

Il file "shared-mem-with-semaphore.c" è un esempio di due processi che accedono allo stesso segmento di memoria usando un semaforo per sincronizzare i loro accessi.


Creazione di una ID per una risorsa SysV - ftok( )

Uno dei problemi maggiori del SysV IPC riguarda la scelta di un unico ID per tutti i processi che, per correttezza, deve essere univoco e non dipendere dalla chiave di altri semafori relativi ad altri programmi che sono in esecuzione nel sistema: la ftok ( ), che utilizza due parametri (il percorso del file e un carattere, genera uno o più ID. Come procede la ftok: cerca l' "i-node", lo combina con il secondo parametro e genera l'ID.


// ID ritornato da ftok( )
key_t set_key;

// generazione di un'unica chiave per il set usando la directory "/usr/local/lib/ourprojectdir"
set_key = ftok("/usr/local/lib/ourprojectdir", 'a');
if (set_key == -1)

// impiego della 'set_key' per generare un ID per il set
sem_set_id = semget(set_key, 1, IPC_CREAT | 0600);

E' bene non rimuovere il file onde evitare che chiamate successive della ftok generino una nuova, diversa da quella precedente.




Privacy




Articolo informazione


Hits: 4819
Apprezzato: scheda appunto

Commentare questo articolo:

Non sei registrato
Devi essere registrato per commentare

ISCRIVITI



Copiare il codice

nella pagina web del tuo sito.


Copyright InfTub.com 2024