Dopo aver visto un esempio su come generare nuovi processi tramite l’utilizzo della chiamata fork(), ecco un altro esempio che mostra come far comunicare tra loro i processi tramite l’utilizzo delle code.
#include <stdio.h> #include <stdlib.h> #include <string.h> // librerie necessarie per l'utilizzo delle code di messaggi #include <sys/ipc.h> #include <sys/msg.h> // dimensione del messaggio #define DIM_MSG 128 // struttura 'msg' che contiene il tipo e il testo del messaggio typedef struct { long mtype; char mtext[DIM_MSG]; } msg; void produttore(int coda); void consumatore(int coda); int main() { // il "descrittore di coda" è un valore ritornato dalla funzione msgget() che permette al processo di riferirsi a quella coda int ds_coda; // la "chiave" di una coda è un numero intero positivo univoco tramite il quale i processi identificano una coda // con il valore speciale IPC_PRIVATE si specifica una nuova coda non ancora creata key_t chiave = IPC_PRIVATE; // IPC_CREAT specifica che se una coda con la stessa chiave non esiste, allora verrà creata // con IPC_EXCL il sistema assicura che sia il processo chiamante ad aver creato la coda // 0660 è un ottale che rappresenta i permessi, analogamente ai permessi del filesystem UNIX ds_coda = msgget(chiave, IPC_CREAT|IPC_EXCL|0660); // si ferma nel caso di errore durante la creazione della coda if (ds_coda == -1) { printf("Errore nella chiamata msgget().n"); exit(1); } // crea i due processi figli "produttore" e "consumatore" if (fork() != 0) { if (fork() != 0) { // il processo padre aspetta che i figli terminino wait(NULL); wait(NULL); } else produttore(ds_coda); } else consumatore(ds_coda); // msctl è la chiamata per modificare le code // il parametro IPC_RMID rimuove la coda associata a "ds_coda" msgctl(ds_coda, IPC_RMID, NULL); exit(0); } // tramite una coda, il "produttore" legge le stringhe da tastiera e le mette in coda void produttore(int coda) { msg messaggio; printf("Inserire i messaggi ('quit' per terminare): n"); do { // legge la stringa di dimensione DIM_MSG e la assegna a 'messaggio.mextext' fgets(messaggio.mtext, DIM_MSG, stdin); messaggio.mtype = 1; // manda la stringa alla coda, restituendo un messaggio di allerta in caso di errore // con il parametro IPC_NOWAIT la funzione 'msgsnd' restituisce errore se trova la coda piena, altrimenti aspetterebbe fino a quando non si libera lo spazio sufficiente nella coda per aggiungere il messaggio if (msgsnd(coda, &messaggio, strlen(messaggio.mtext)+1, IPC_NOWAIT) == -1) { printf("Errore nell'inserimento del messaggio.n"); exit(1); } printf("nMessaggio inviato: %sn", messaggio.mtext); } while (strcmp(messaggio.mtext, "quitn") != 0); // ripete il ciclo fino a quando non si inserisce "quit" exit(0); } // il "consumatore" legge i messaggi dalla coda e li stampa in output void consumatore(int coda) { msg messaggio; do { // legge un messaggio assegnandolo alla variabile 'messaggio' e fermandosi se non ce ne sono if (msgrcv(coda, &messaggio, DIM_MSG, 1, 0) == -1) { printf("Errore durante l'estrazione del messaggio.n"); exit(1); } printf("Messaggio ricevuto: %sn", messaggio.mtext); } while (strcmp(messaggio.mtext, "quitn") != 0); // ripete il ciclo fino a quando non incontra "quit" exit(0); }