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.

Codice sorgente:

#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);
}

About OpenProgrammers

Programmatore per passione. Mi piace condividere qualsiasi idea o informazione utile, per questo motivo ho realizzato il blog.