Anteprima
Vedrai una selezione di 20 pagine su 109
Sistemi operativi - Appunti Pag. 1 Sistemi operativi - Appunti Pag. 2
Anteprima di 20 pagg. su 109.
Scarica il documento per vederlo tutto.
Sistemi operativi - Appunti Pag. 6
Anteprima di 20 pagg. su 109.
Scarica il documento per vederlo tutto.
Sistemi operativi - Appunti Pag. 11
Anteprima di 20 pagg. su 109.
Scarica il documento per vederlo tutto.
Sistemi operativi - Appunti Pag. 16
Anteprima di 20 pagg. su 109.
Scarica il documento per vederlo tutto.
Sistemi operativi - Appunti Pag. 21
Anteprima di 20 pagg. su 109.
Scarica il documento per vederlo tutto.
Sistemi operativi - Appunti Pag. 26
Anteprima di 20 pagg. su 109.
Scarica il documento per vederlo tutto.
Sistemi operativi - Appunti Pag. 31
Anteprima di 20 pagg. su 109.
Scarica il documento per vederlo tutto.
Sistemi operativi - Appunti Pag. 36
Anteprima di 20 pagg. su 109.
Scarica il documento per vederlo tutto.
Sistemi operativi - Appunti Pag. 41
Anteprima di 20 pagg. su 109.
Scarica il documento per vederlo tutto.
Sistemi operativi - Appunti Pag. 46
Anteprima di 20 pagg. su 109.
Scarica il documento per vederlo tutto.
Sistemi operativi - Appunti Pag. 51
Anteprima di 20 pagg. su 109.
Scarica il documento per vederlo tutto.
Sistemi operativi - Appunti Pag. 56
Anteprima di 20 pagg. su 109.
Scarica il documento per vederlo tutto.
Sistemi operativi - Appunti Pag. 61
Anteprima di 20 pagg. su 109.
Scarica il documento per vederlo tutto.
Sistemi operativi - Appunti Pag. 66
Anteprima di 20 pagg. su 109.
Scarica il documento per vederlo tutto.
Sistemi operativi - Appunti Pag. 71
Anteprima di 20 pagg. su 109.
Scarica il documento per vederlo tutto.
Sistemi operativi - Appunti Pag. 76
Anteprima di 20 pagg. su 109.
Scarica il documento per vederlo tutto.
Sistemi operativi - Appunti Pag. 81
Anteprima di 20 pagg. su 109.
Scarica il documento per vederlo tutto.
Sistemi operativi - Appunti Pag. 86
Anteprima di 20 pagg. su 109.
Scarica il documento per vederlo tutto.
Sistemi operativi - Appunti Pag. 91
1 su 109
D/illustrazione/soddisfatti o rimborsati
Disdici quando
vuoi
Acquista con carta
o PayPal
Scarica i documenti
tutte le volte che vuoi
Estratto del documento

CODA

if( numProdWaitingAndSignalled >= (NUMBUFFER-numBufferPieni)){ printf("Prod ENTRA CODA\n"); numProdWaiting++; DBGpthread_cond_wait(&condProd,&mutex,Plabel); numProdWaiting--; numProdWaitingAndSignalled--; } else { printf("Prod SALTA CODA\n"); } /* riempie il buffer col dato prodotto prima */ add_to_tail_FTQ( &global_ftq, buffer ); numBufferPieni++; /* SE ho qualche Cons in coda non segnalato (cioe' SEnumConsWaitingAndSignalled < numConsWaiting ) E SE i Cons in Coda e signalled SONO < dei bufferpieni (cioe' SE numConsWaitingAndSignalled <numBufferPieni) allora POSSO ABILITARE altri Cons aproseguire e uscire dalla wait.*/ if( ( numConsWaitingAndSignalled < numConsWaiting )&&( numConsWaitingAndSignalled < numBufferPieni ) ){ /* risveglio un Consumatore per svuotare un buffer */ DBGpthread_cond_signal(&condCons,Plabelsignal); numConsWaitingAndSignalled++; } /* rilascio mutua esclusione */
/*DBGpthread_mutex_unlock(&mutex,Plabel);}*/
pthread_exit(NULL);
}

void *Consumatore (void *arg){
    int indice;
    uint64_t valPrelevato=0;
    STRUCTUREDBUFFER buffer; /* il singolo buffer */
    indice=*((int*)arg);
    free(arg);
    while(1) {
        DBGpthread_mutex_lock(&mutex,Clabel);
        /* se tutti i buffer sono vuoti allora aspettiamo che unProd ci risvegli
        In generale il problema e' che se ho NUMBUFFER buffer enumBufferPieni buffer pieni
        enumConsWaiting Cousumatori in coda
        enumConsWaitingAndSignalled Consumatori in coda e gia' abilitati
        a proseguire (cioe' signalled)
        SE i Cons in Coda e Signalled SONO>= dei buffer pieni cioe SE numConsWaitingAndSignalled >=numBufferPieni
        allora NON POSSO FAR PROSEGUIRE dei Cons SENZA METTERLI NELLA CODA */
        if( numConsWaitingAndSignalled >= numBufferPieni ) {
            printf("Cons ENTRA CODA\n")
            numConsWaiting++;
            DBGpthread_cond_wait(&condCons,&mutex,Clabel);
            numConsWaiting--;
            numConsWaitingAndSignalled--;
        } else {
            printf("Cons %s SALTA
CODA
",Clabel);fflush(stdout);}/* prendo cio' che c'e' nel buffer */remove_from_head_FTQ(&global_ftq, &buffer);valPrelevato=buffer.val;numBufferPieni--; /* SE i Prod in Coda e signalled SONO >= dei buffer vuoti NONPOSSO ABILITARE altri Prod in coda a proseguire invece SE hoqualche Prod in coda non segnalato (cioe' SEnumProdWaitingAndSignalled < numProdWaiting ) E SE i Prod inCoda e signalled SONO < dei buffer pieni cioe' SEnumProdWaitingAndSignalled < (NUMBUFFER-numBufferPieni)POSSO ABILITARE altri Prod a proseguire e uscire da wait.*/if( (numProdWaitingAndSignalled < numProdWaiting ) &&(numProdWaitingAndSignalled < (NUMBUFFER-numBufferPieni))){ /* risveglio 1 Prod per riempire il buffer svuotato */DBGpthread_cond_signal(&condProd,Clabelsignal);numProdWaitingAndSignalled++;}/* rilascio mutua esclusione */DBGpthread_mutex_unlock(&mutex,Clabel);/* fuori da mutua esclusione, uso il dato supponiamo che ci voglia 1

secondoprintf("Cons %s USA dato %lu \n", Clabel, val );
fflush(stdout);
DBGsleep(1,Clabel);
*/}

pthread_exit(NULL);
}

int main (int argc, char* argv[] ){
    pthread_t thProd[NUMPROD];
    pthread_t thCons[NUMCONS];
    int rc, i, *intptr;
    void *ptr;

    /* inizializzo la coda globale */
    init_FTQ( NUMBUFFER, &global_ftq );

    rc = pthread_cond_init(&condProd, NULL);
    if( rc ) PrintERROR_andExit(rc,"pthread_cond_init failed");

    rc = pthread_cond_init(&condCons, NULL);
    if( rc ) PrintERROR_andExit(rc,"pthread_cond_init failed");

    rc = pthread_mutex_init(&mutex, NULL);
    if( rc ) PrintERROR_andExit(rc,"pthread_mutex_init failed");

    /* all'inizio i Cons devono aspettare il primo Prod */
    numBufferPieni=0; /* 0 o 1 */
    numProdWaiting=0;
    numProdWaitingAndSignalled=0;
    numConsWaiting=0;
    numConsWaitingAndSignalled=0;

    for(i=0;i<NUMCONS;i++) {
        intptr=malloc(sizeof(int));
        if( !intptr ) { 
            printf("malloc failed\n");
            exit(1);
        }


}*intptr=i;
rc=pthread_create(&(thCons[i]),NULL,Consumatore,(void*)intptr);
if(rc) PrintERROR_andExit(rc,"pthread_create failed");
}

for(i=0;i<NUMPROD;i++) {
    intptr=malloc(sizeof(int));
    if( !intptr ) {
        printf("malloc failed\n");
        exit(1);
    }
    *intptr=i;
    rc=pthread_create(&(thProd[i]),NULL,Produttore,(void*)intptr);
    if(rc) PrintERROR_andExit(rc,"pthread_create failed");
}

for(i=0;i<NUMPROD;i++) {
    rc = pthread_join(thProd[i], &ptr );
    if(rc) PrintERROR_andExit(rc,"pthread_join failed");
}

for(i=0;i<NUMCONS;i++) {
    rc = pthread_join(thCons[i], &ptr );
    if(rc) PrintERROR_andExit(rc,"pthread_join failed");
}

rc = pthread_mutex_destroy(&mutex);
if(rc) PrintERROR_andExit(rc,"pthread_mutex_destroy failed");

rc = pthread_cond_destroy(&condProd);
if(rc) PrintERROR_andExit(rc,"pthread_cond_destroy failed");

rc = pthread_cond_destroy(&condCons);
if(rc) PrintERROR_andExit(rc,"pthread_cond_destroy failed");

failed");return(0); }

Lettori e Scrittori

Un programma è composto da due tipi di thread, i Lettori e gli Scrittori. Tutti i thread accedono ad uno stesso buffer comune.

Entrambi i tipi di thread eseguono un loop infinito, durante il quale i Lettori accedono al buffer comune leggendone il contenuto, mentre gli Scrittori accedono al buffer comune in scrittura cioè modificandone il contenuto. Possono esistere uno o più thread Lettori ed uno o più thread Scrittori.

Quando uno Scrittore accede al buffer, poiché ne sta modificando il contenuto, nessun altro thread può accedere al buffer. Quando un Lettore accede al buffer, poiché non ne modifica il contenuto, anche altri Lettori possono accedere in contemporanea al buffer. Quindi, se nessuno Scrittore accede al buffer, molti Lettori possono accedere insieme.

Soluzione semplice ma sbagliata potrebbe essere quella di proteggere in mutua esclusione il buffer comune, permettendo l'accesso ad un

solothread per volta, indipendentemente dal fatto che questo thread sia un Lettore o uno Scrittore. In questo modo, però, il sistema non consente più Lettori di accedere al buffer in contemporanea, mentre ciò sarebbe possibile senza problemi, poiché i Lettori non modificano il contenuto del buffer. Una soluzione corretta consente che, fino a che c'è un Lettore già in lettura sul buffer, un altro lettore possa accedere al buffer. Questo permette a più lettori di accedere al buffer contemporaneamente, con una sorta di passaggio di testimone. Il limite di tale soluzione è la Starvation (morte di fame) degli Scrittori: gli Scrittori rischiano di non poter mai accedere al buffer se c'è una sequenza ininterrotta di accessi al buffer da parte dei Lettori. I 5 filosofi Cinque filosofi sono a tavola per mangiare. Per mangiare occorrono due forchette. Alla destra di ciascun filosofo c'è una forchetta. Per mangiare

Il filosofo deve prendere sia la forchetta alla sua destra che la forchetta alla sua sinistra. Dopo aver mangiato, il filosofo mette a posto le forchette e pensa per un po'. Poi gli viene ancora fame e cerca di mangiare. Evidentemente non potranno mangiare tutti contemporaneamente, ma occorre assicurare il massimo grado di parallelismo. Cioè si deve permettere che due filosofi (non adiacenti) mangino assieme utilizzando 4 delle 5 forchette.

Per semplicità si indicizzano i filosofi da 0 a 4 in senso orario cominciando da quello più in alto. Andrebbe evitato il deadlock: se ciascun filosofo prende la forchetta di sinistra e poi si mette in attesa di quella di destra, si bloccano tutti indefinitamente. Se si accorgono del blocco e tutti posano assieme la loro forchetta e poi le riprendono assieme, allora potrebbero non mangiare mai nessuno (starvation). Per evitare deadlock bisogna prendere due forchette insieme solo quando sono libere entrambe, oppure prendere le

forchette in ordine diverso (tutti prendono per prima la forchetta alla destra, uno solo la forchetta alla sinistra).

Il barbiere sonnolento

Nel negozio di un barbiere ci sono N sedie in cui stanno i clienti in attesa del taglio ed una poltrona su cui sta il cliente mentre viene servito e dove pisola il barbiere mentre aspetta che arrivi un qualche cliente. Se non ci sono clienti il barbiere pisola. Quando un cliente arriva, se c'è qualche sedia libera allora entra e si siede aspettando di essere servito. Se tutte le sedie sono occupate invece se ne va subito. Se le sedie sono tutte vuote e il barbiere sta pisolando, il cliente si siede e poi lo chiama per svegliarlo. Allora il barbiere si sveglia, fa accomodare il cliente in poltrona e comincia a servirlo. Dopo il taglio, i clienti se ne vanno ma dopo qualche giorno tornano per un nuovo taglio.

Il barbiere cortese

Nella soluzione manca un dettaglio: come fa il cliente a sapere che il barbiere ha finito di servirlo ?

Si aggiunge

Perciò un dettaglio alla descrizione precedente, ottenendo così il problema del barbiere cortese ovvero il Barbiere appisolato che saluta: il barbiere fa accomodare il cliente in poltrona e comincia a servirlo. Quando finisce di servirlo, il barbiere saluta il cliente per fargli capire che se ne deve andare. Dopo che il cliente si è accomodato sulla poltrona per il taglio, il cliente aspetta che il barbiere lo saluti e non appena il barbiere lo saluta, il cliente si alza e se ne va. Chi garantisce che quando il barbiere fa la signal su Saluto il cliente abbia già fatto la wait su Saluto? Con l'algoritmo precedente potrebbe capitare questo: un Cliente C1 è fermo sulla pthread_cond_wait( &condBarbiereLibero, &mutex); il barbiere chiama un cliente in attesa con la pthread_cond_signal( &condBarbiereLibero); e quindi abilita il cliente C1 a uscire dalla wait. Poi il barbiere rilascia la mutua esclusione. Ora il cliente C1 potrebbe proseguire e uscire.

dalla wait acquisendo la mutuaesclusione. Però lo scheduler decide di far proseguire ancora il barbiere e il cliente rimane ancora nella wait su condBarbiereLibero. Quindi il barbiere prende ancora la mutua esclusione pthread_mutex_lock ( &mutex ); e prosegue in mutua esclusione. A questo punto il barbiere saluta il cliente con pthread_cond_signal( &condSaluto ); ma la signal avviene quando ancora il cliente C1 sta nell'await su condBarbiereLibero, e quindi NON ha ancora eseguito la wait su condSaluto. La signal non ha effetto, è come se fosse persa. Quando il client C1 arriverà a fare la wait su condSaluto si bloccherà. Occorre una nuova sincronizzazione semplice tra due soli thread. Si potrebbe usare una nuova variabile globale int.
Dettagli
A.A. 2021-2022
109 pagine
1 download
SSD Scienze matematiche e informatiche INF/01 Informatica

I contenuti di questa pagina costituiscono rielaborazioni personali del Publisher Nobody_scuola_1990 di informazioni apprese con la frequenza delle lezioni di Elementi di Sistemi operativi e studio autonomo di eventuali libri di riferimento in preparazione dell'esame finale o della tesi. Non devono intendersi come materiale ufficiale dell'università Università degli Studi di Bologna o del prof Ghini Vittorio.