Costuzione di una semplice agenda elettronica by hellais

VIEWS: 34 PAGES: 19

									Costruzione di una semplice Agenda telefonica Elettronica
Esercizio sull'uso delle principali system call Unix

Agenda telefonica
1. L'agenda e' costituita da un semplice file di testo. Ogni riga e' formata da: Cognome nome numero-telefonico

ad esempio: Bollati Mario 0116792932 Corelli Simona 0234743212 Magni Giorgio 06431432143 .......... ........... .................

Comandi per gestire l'agenda
• cerca cognome
– stampa sul terminale la riga del file agenda che contiene cognome

• inserisci cognome nome numero-telefonico
– inserisce nel file agenda la riga formata da cognome, nome e numero di telefono

• rimuovi cognome
– rimuove dall'agenda la riga contenente cognome

implementazione mediante demone e code di messaggi
P2 P3 P4

coda delle richieste di accesso all'agenda

P1

demone

file "agenda"

bassi mario 43214321
Carli Bruno 0143243 Massi Rino 9434232 ....... ....... .............

Implementazione mediante demone e code di messaggi
• Il processo demone viene lanciato in back ground e resta in attesa sulla coda delle richieste di accesso all'agenda. • L'accesso al file "agenda" e' gestito unicamente dal demone: le varie operazioni sono così automaticamente serializzate.

Implementazione mediante demone e code di messaggi
• le tre operazioni possono essere richieste al demone usando messaggi di tipo diverso (basta usare un numero diverso per ogni tipo di messaggio) • il processo richiedente attende sulla coda la risposta del demone che restituisce il numero di telefono (per cerca) o semplicemente segnala il completamento dell'operazione (per inserisci e rimuovi)

Implementazione mediante demone e code di messaggi
• Come fare in modo che il demone comunichi direttamente ed esclusivamente con il processo che attende la sua risposta? • Basta inserire nella stringa del messaggio il numero del processo richiedente: pid. Il demone risponde con un messaggio di tipo pid, che solo il processo stesso puo' ricevere.

Implementazione mediante semafori e accesso diretto al file "agenda" in modo mutuamente esclusivo
P1 P2 P3 P4

P:
bassi mario 43214321 Carli Bruno 0143243

file "agenda"

Massi Rino 9434232 ....... ....... .............

area ad accesso mutuamente esclusivo

V:

Implementazione mediante semafori e accesso diretto al file "agenda"
• Le operazioni su "agenda" devono avvenire in mutua esclusione, attraverso l'uso di un semaforo binario inizializzato a 1 • ognuno dei tre programmi, per accedere al file agenda deve prima eseguire una P sul semaforo, e poi puo' aprire il file e leggerlo o modificarne il contenuto. • Alla fine delle operazioni sul file il processo deve eseguire una V sul semaforo prima di terminare.

Alcuni consigli
• Tenete tutti i programmi e il file agenda in un'unica directory. • Come fanno i programmi a sapere l'identificatore della coda o semaforo da usare? Un modo semplice e' usare un file id_file per contere l'identificativo della coda o del semaforo:
– nel caso della coda, e' il demone che preleva la coda e scrive il suo identificatore dentro id_file – Nel caso del semaforo, un programma ad hoc preleva il semaforo, scrive il suo identificatore dentro id_file e termina.

• I programmi leggono dentro id_file per conoscere l'identificatore da usare.

Alcuni consigli
• C'e' pero' un modo piu' elegante per far usare ad un insieme di programmi la coda (o il semaforo): msgid = msgget(KEY, IPC_CREAT | 666) • KEY e' un numero intero concordato da tutti i programmi che vogliono usare la coda • Alla prima chiamata della msgget con KEY, viene creata una nuova coda e il suo identificatore msgid associato biunivocamente a KEY. • successivamente, qualsiasi altro programma che chiama msgget con lo stesso valore di KEY riceve il msgid associato a KEY.

Alcuni consigli
• ad esempio, in un file mydef.h possiamo mettere:
#define LA_NOSTRA_CODA 12345

• e in ogni programma che deve usare LA_NOSTRA_CODA:
#include mydef.h ..... ..... msgid = msgget(LA_NOSTRA_CODA,IPC_CREAT|666);

• Notate: se 2 o piu' processi condividono lo stesso padre, allora si puo' fare anche in un altro modo:
msgid = msgget(getppid(), IPC_CREAT|666);

Alcuni consigli
• quando avete finito di provare i programmi, ricordatevi di rimuovere le risorse prelevate (il semaforo o la coda) e, se presente, di uccidere il processo demone. • Per compilare un programma C: gcc prog.c -o prog

Alcuni consigli
• potete usare solo "istruzioni C", se preferite, ma non scordatevi che puo' essere comodo usare anche i comandi shell. • Ad esempio, per rimuovere la riga contentente cognome:
$> grep –v cognome > agenda.tmp $> mv agenda.tmp agenda

• la system call system puo' essere usata per eseguire comandi shell da un programma C

per provare il funzionamento dei programmi :
• ovviamente lanciando direttamente i 3 comandi. • potete pero' anche scrivere un programma che ciclicamente sceglie uno tra i comandi cerca inserisci e rimuovi e lo esegue. • per produrre l'effetto di piu' richieste di accesso concorrente all'agenda, potete costruire un programma che si forka 2 o 3 volte, e ogni figlio esegue i comandi di uso dell'agenda.

consigli sul funzionamento del progr. di generazione delle richieste all'agenda:
• ogni figlio esegue un ciclo un numero finito di volte (ad esempio 100) oppure indefinitamente. • ad ogni ciclo:
– sleep un tempo random di 1 o 2 secondi – scegli in modo random uno dei tre comandi – esegui comando

• comando puo' essere eseguito con una exec o piu' semplicemente con una system

consigli sul funzionamento del progr. di generazione delle richieste all'agenda:
• il padre dei due figli che inviano ciclicamente le richieste puo' mettersi in attesa (wait) della loro terminazione, e poi rimuovere le risorse (se necessario uccidere il demone) e terminare. • soprattutto nel caso in cui i figli ciclano all'infinito, potete inoltre prevedere un meccanismo di gestione della terminazione mediante signal e kill

terminazione dell'intero sistema mediante signal e kill
• il programma di generazione delle richieste all'agenda definisce una procedura di terminazione da eseguire alla ricezione di un segnale inviato da terminale mediante kill:
$> kill –SIGUSR1 pid

• la procedura di terminazione rimuove le risorse (coda o semaforo) e termina il programma. ATTENZIONE: e' possibile far terminare anche i figli (e se necessario il demone)?

struttura generale del programma
{ termina(...) {...} signal(termina,SIGUSR1); fork() if figlio for (;;) { sleep(1,2); system(estrai,rimuovi,inserisci) } else fork() if figlio for (;;) {sleep(1,2); system(estrai,rimuovi,inserisci) } else {wait() }


								
To top