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