Il sistema operativo LINUX Semafori Semaforo Sommario Sommario
Transcript
Il sistema operativo LINUX Semafori Semaforo Sommario Sommario
Sistemi operativi – Modulo II I semafori Il sistema operativo LINUX Semafori Giorgio Di Natale <[email protected]> Stefano Di Carlo <[email protected]> Politecnico di Torino Dip. Automatica e Informatica Semaforo • Un semaforo è una variabile sv che può assumere solo valori positivi e sulla quale sono definite le operazioni: – semaphor_wait(sw): • se sv è zero blocca il processo chiamante • se sv è maggiore di zero decrementa sv – semaphor_signal(sw): • se un processo è in attesa lo sblocca • altrimenti incrementa sv Sommario • Gestione dei semafori tramite pipe – Introduzione – Primitive – Esempio • Gestione dei insiemi di semafori in Unix Sommario • Gestione dei semafori tramite pipe – Introduzione – Primitive – Esempio • Gestione dei insiemi di semafori in Unix Gestione di semafori tramite pipe • Il semaforo è una variabile di tipo contatore. • L’operazione wait è bloccante se il contatore è uguale a 0. Se il contatore è uguale a 0, la wait è bloccante. In ogni caso decrementa il valore del contatore • L’operazione signal incrementa il valore del contatore Uso delle pipe • Il semaforo è implementato con una pipe signal G. Di Natale, S. Di Carlo Pipe wait 1 Sistemi operativi – Modulo II I semafori Uso delle pipe • Il semaforo è implementato con una pipe • Il contatore del semaforo è realizzato tramite il concetto di token signal Pipe wait Uso delle pipe • Il semaforo è implementato con una pipe • Il contatore del semaforo è realizzato tramite il concetto di token • La signal è effettuata con un’operazione di write di un token sulla pipe write Pipe Uso delle pipe • Il semaforo è implementato con una pipe • Il contatore del semaforo è realizzato tramite il concetto di token • La signal è effettuata con un’operazione di write di un token sulla pipe • La wait è effettuata con un’operazione di read di un token dalla pipe write Pipe Sommario • Gestione dei semafori tramite pipe – Introduzione – Primitive – Esempio • Gestione dei insiemi di semafori in Unix read Primitive • semaphor_init(sw) • semaphor_wait(sw) • semaphor_signal(sw) G. Di Natale, S. Di Carlo wait Primitive • semaphor_init(sw) • semaphor_wait(sw) • semaphor_signal(sw) 2 Sistemi operativi – Modulo II I semafori semaphore_init (sw) #include <unistd.h> void semaphore_init (int* sw) { if (pipe(sw) == -1) { printf (“Error”); exit (-1); } } Primitive • semaphor_init(sw) • semaphor_wait(sw) • semaphor_signal(sw) semaphore_signal (sw) #include <unistd.h> void semaphore_signal (int* sw) { if (write(sw[0],”X”,1) != 1) { printf (“Error”); exit (-1); } } semaphore_wait (sw) #include <unistd.h> void semaphore_wait (int* sw) { char buffer; if (read(sw[1],&buffer,1) != 1) { printf (“Error”); exit (-1); } } G. Di Natale, S. Di Carlo Primitive • semaphor_init(sw) • semaphor_wait(sw) • semaphor_signal(sw) Sommario • Gestione dei semafori tramite pipe – Introduzione – Primitive – Esempio Gestione dei insiemi di semafori in Unix • 3 Sistemi operativi – Modulo II I semafori Esempio Esempio int main() { int sem[2]; pid_t fork_result; if (fork_result == 0) { // child semaphore_wait (sem); printf("Wait done.\n"); } else { // parent printf("Sleep 5s.\n"); sleep (5); semaphore_signal (sem); printf("Signal done.\n"); } return 0; semaphore_init (sem); fork_result = fork(); if (fork_result == -1) { fprintf(stderr, "Fork failure"); exit(EXIT_FAILURE); } } Sommario • Gestione dei semafori tramite pipe – Introduzione – Primitive – Esempio • Gestione dei insiemi di semafori in Unix Gestione semafori in UNIX System call per la gestione di insiemi di semafori: #include <sys/sem.h> int semget (key_t, int num_sems, int sem_flags); int semop (int sem_id, struct sembuf *sem_ops, size_t num_sem_ops); int semctl(int sem_id, int sem_num, int command, …); Strutture dati struct sem_buf { short sem_num; short sem_op; short sem_flg; } G. Di Natale, S. Di Carlo #include “semun.h” struct semun { int val; struct semid_ds *buf; unsigned short *array; } Strutture dati struct sem_buf { short sem_num; Value for short sem_op; SETVAL short sem_flg; } #include “semun.h” struct semun { int val; struct semid_ds *buf; unsigned short *array; } 4 Sistemi operativi – Modulo II I semafori Strutture dati struct sem_buf { short sem_num; short sem_op; Buffer for short sem_flg; IPC_STAT, } IPC_SET Strutture dati #include “semun.h” struct semun { int val; struct semid_ds *buf; unsigned short *array; } struct sem_buf { short sem_num; short sem_op; short sem_flg; Array for } GETALL, SETALL #include “semun.h” struct semun { int val; struct semid_ds *buf; unsigned short *array; } /* * semaphore_wait changes the semaphore by -1 (waiting) */ /* semaphore_sig is similar except for setting the sem_op * part of the sembuf structure to 1, * so that the semaphore becomes available */ static int semaphore_wait(void) { struct sembuf sem_b; static int semaphore_sig(void) { struct sembuf sem_b; sem_b.sem_num = 0; sem_b.sem_op = 1; /* V() */ sem_b.sem_flg = SEM_UNDO; if (semop(sem_id, &sem_b, 1) == -1) { fprintf(stderr, "semaphore_sig failed\n"); return(0); } return(1); sem_b.sem_num = 0; sem_b.sem_op = -1; /* P() */ sem_b.sem_flg = SEM_UNDO; if (semop(sem_id, &sem_b, 1) == -1) { fprintf(stderr, "semaphore_wait failed\n"); return(0); } return(1); } } /* The function set_semvalue initializes the semaphore to * value using the SETVAL command in a * semctl call. We need to do this before we can use * the semaphore */ /* The del_semvalue function has almost the same form, * except the call to semctl uses * the command IPC_RMID to remove the semaphore's ID */ static int set_semvalue(int value) { union semun sem_union; static void del_semvalue(void) { union semun sem_union; sem_union.val = value; if (semctl(sem_id, 0, SETVAL, sem_union) == -1) return(0); return(1); if (semctl(sem_id, 0, IPC_RMID, sem_union) == -1) fprintf(stderr, "Failed to delete semaphore\n"); } } G. Di Natale, S. Di Carlo 5 Sistemi operativi – Modulo II #include <unistd.h> #include <stdlib.h> #include <stdio.h> I semafori Esempio #include <sys/types.h> #include <sys/ipc.h> #include <sys/sem.h> #include "semun.h" static static static static int set_semvalue(void); void del_semvalue(void); int semaphore_wait(void); int semaphore_signal(void); int main(int argc, char *argv[]) { int i; int pause_time; char op_char = 'O'; srand((unsigned int)getpid()); sem_id = semget((key_t)1234, 1, 0666 | IPC_CREAT); if (argc > 1) { if (!set_semvalue()) { fprintf(stderr, "Failed to init semaphore\n"); exit(EXIT_FAILURE); } op_char = 'X'; sleep(2); } static int sem_id; for(i = 0; i < 10; i++) { if (!semaphore_wait()) exit(EXIT_FAILURE); printf("%c", op_char);fflush(stdout); pause_time = rand() % 3; sleep(pause_time); printf("%c", op_char);fflush(stdout); if (!semaphore_signal()) exit(EXIT_FAILURE); pause_time = rand() % 2; sleep(pause_time); } printf("\n%d - finished\n", getpid()); if (argc > 1) { sleep(10); del_semvalue(); } exit(EXIT_SUCCESS); } G. Di Natale, S. Di Carlo 6