03 - Sincronizzazione di processi con semafori
I semafori sono un altro strumento, oltre ai segnali, a disposizione dei programmatori per sincronizzare i processi. A differenza dei segnali possono essere visti come una sorta di variabile in comune ai vari programmi lei cui propriet� possono essere modificate durante l'esecuzione. Queste elementi richiedono l'uso di tre librerie:
- sys/types.h
- sys/ipc.h
- sys/sem.h
Le principali funzioni di gestione dei semafori sono:
- semget (key_t key, int num_sem, short flags): La funzione crea un gruppo di semafori, che viene identificato con un numero positivo intero. I semafori dentro al gruppo sono identificati partendo a contare da 0 con numeri crescenti positivi.
- key: � una chiave necessaria per la generazione del set di semafori; pu� essere un numero qualsiasi, ma per essere sicuri che non vi siano duplicati si pu� usare ftok(), studiata apposta. Se tale valore vale IPC_PRIVATE, la creazione dei semafori � forzata.
- num_sem: indica il numero di semafori appartenenti al gruppo.
- flags: indica gli attributi del gruppo di semafori: IPC_CREAT crea i semafori. IPC_EXCL verifica che i semafori esistano. E' possibile specificare anche comandi di impostazione dei permessi.
Riassumento, le condizioni per cui la creazione di un gruppo di semafori va a buon fine sono:
- L'uso di una chiave non duplicata e la presenza del flag IP_CREAT.
- L'uso, come chiave, del comando IPC_PRIVATE.
- semctl(int semid, int semnum, int cmd, union argomenti): esegue una operazione cmd su un semaforo semnum di un gruppo semid. Le operazioni sono:
- IPC_RMID: rimuove il set di semafori.
- GETVAL: legge il valore di un semaforo.
- SETVAL: imposta il valore di un semaforo.
- GETPID: ottiene il PID dell'ultimo processo che ha usato il semaforo.
Se � necessario passare alla funzione dei valori, pu� essere fatto con l'unione argomenti, in particolare SETVAL e GETVAL.
- semop (int sem_id, struct sembuf *operation, int num_elements): esegue una operazione sui semafori. Le operazioni possibili sono:
- sem_id: indica il gruppo di semafori.
- operation: vettore che indica su quale semaforo agire e quale operazione effetturare. E' composto da tre elementi:
- sem_num: numero del semaforo all'interno del gruppo
- sem_op: operazione da eseguire. Se sem_op � negativo, viene eseguita una wait(). Se sem_op � positivo viene eseguita una signal().
- sem_flg: utilizzato per compiere operazioni particolari, tra cui:
- SEM_UNDO: quando il processo termina, imposta il semaforo al suo vecchio valore
- IPC_NOWAIT: non sospende il processo, ma restituisce -1.
- num_elements: indica il numero di elementi allocati per il vettore operation.
Di seguito c'� un esempio che mostra le principali operazioni eseuibili con i semafori.
#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <sys/sem.h>
#include <sys/errno.h>
#if defined(__GNU_LIBRARY__) && !defined(_SEM_SEMUN_UNDEFINED)
/* L'unione semun � gi� definita in <sys/sem.h> */
#else
/* Secondo X/OPEN dobbiamo definire semun da soli */
union semun {
int val; /* Valore per SETVAL */
struct semid_ds *buf; /* buffer per IPC_STAT, IPC_SET */
unsigned short int *array; /* array per GETALL, SETALL */
struct seminfo *__buf; /* buffer per IPC_INFO */
} pippo; // Alloco la unione semun
#endif
struct sembuf pluto; // Alloco la struttura pluto di tipo sembuf
main()
{
int semaforo;
semaforo = semget(IPC_PRIVATE, 1, 0777);
if(semaforo > 0)
{
printf("Creato il semaforo: %d\n", semaforo);
printf("Sto per leggere il semaforo\n");
semctl(semaforo,0,GETALL,&pippo);
printf("Valore: %d\n",pippo.val);
printf("Sto per impostare il valore del semaforo a 3\n");
pippo.val = 3;
semctl(semaforo,0,SETVAL,pippo);
printf("Sto per leggere il semaforo\n");
semctl(semaforo,0,GETALL,&pippo);
printf("Valore: %d\n",pippo.val);
pluto.sem_num = 0;
pluto.sem_op = -1;
printf("Attesa sul semaforo\n");
semop(semaforo,&pluto,1);
printf("Sto per leggere il semaforo\n");
semctl(semaforo,0,GETALL,&pippo);
printf("Valore: %d\n",pippo.val);
pluto.sem_num = 0;
pluto.sem_op = 1;
printf("Segnale sul semaforo\n");
semop(semaforo,&pluto,1);
printf("Sto per leggere il semaforo\n");
semctl(semaforo,0,GETALL,&pippo);
printf("Valore: %d\n",pippo.val);
}
}
Fatal error: Call to undefined function sqlite_open() in /membri/giacobbe85/include/commenti.inc.php on line 324
|