Un altro modo per scambiare dati tra processi UNIX è la memoria condivisa. Ogni memoria condivisa ha una chiave che la identifica in modo univoco. Quando un processo vuole utilizzare una memoria condivisa deve attaccarla al proprio spazio di indirizzamento, quando non desidera più utilizzarla può successivamente staccarla anche se essa continuerà ad esistere indipendentemente da ogni processo, a meno che non venga esplicitamente distrutta.
Quando un processo genera un figlio tramite la chiamata fork(), esso eredita le aree condivise di memoria attaccate al padre. Se un processo termina, le relative aree di memoria attaccate vengono staccate ma nono distrutte (a meno che non venga specificato).
Le chiamate shm* per gestire la memoria condivisa e i loro parametri sono spesso simili a quelle msg* che gestiscono le code. Ecco un esempio di due processi fratelli che scambiano numeri tramite l’utilizzo di un’area di memoria condivisa:
#include <stdio.h> #include <stdlib.h> // librerie necessarie per l'utilizzo della memoria condivisa tra processi #include <sys/ipc.h> #include <sys/shm.h> #define MAX_NUMBERS 10 void scrittore(int id); void lettore(int id); int main() { int id_shm; // crea l'area di memoria condivisa id_shm = shmget(IPC_PRIVATE, sizeof(int)*(MAX_NUMBERS+1), IPC_CREAT|IPC_EXCL|0600); if (id_shm == -1) { printf("Errore nella chiamata shmget().n"); exit(1); } // crea un primo processo figlio che scrive nella memoria condivisa if (fork() != 0) // il processo padre attende il termine del primo figlio wait(NULL); else // il primo processo figlio scrive nella memoria condivisa e termina scrittore(id_shm); // crea un secondo processo figlio che legge dalla memoria condivisa if (fork() != 0) // il processo padre attende il termine del secondo figlio wait(NULL); else // il secondo processo figlio legge dalla memoria condivisa e termina lettore(id_shm); // distrugge l'area di memoria condivisa e termina shmctl(id_shm, IPC_RMID, NULL); exit(0); } void scrittore(int id) { int *p; int numero, q=0; printf("n**Processo Scrittore:n"); // la chiamata shmat riporta l'indirizzo di memoria a cui è stata attaccata la memoria condivisa p = (int *)shmat(id, NULL, 0); if (p == (int *)-1) { printf("Errore nella chiamata shmat().n"); exit(1); } do { printf("nScrivi un numero da inserire ('0' per terminare): "); scanf("%d",&numero); if (numero == 0) break; p[q+1] = numero; q++; printf("nNumero inserito: %dn",numero); } while (q < MAX_NUMBERS); // nel primo slot scrive la quantità di numeri depositati p[0] = q; exit(0); } void lettore(int id) { int *p; int i, q=0; printf("n**Processo Lettore:n"); // collega la memoria condivisa con lo spazio di indirizzamento, in sola lettura tramite SHM_RDONLY p = (int *)shmat(id, NULL, SHM_RDONLY); if (p == (int *)-1) { printf("Errore nella chiamata shmat().n"); exit(1); } // legge quanti numeri ci sono nell'area condivisa q = p[0]; for (i = 1; i <= q; i++) printf("%d ", p[i]); printf("n"); exit(0); }