wiki:WikiStart

Version 34 (modified by lorenzo, 10 years ago) (diff)

--

Laboratorio di Sistemi Operativi

TOC(noheading)?

Lezione 1: Introduzione

Slide

Programmi

  • Accesso diretto alla macchina fisica mioboot-nobios-simple.asm
    bits 16                         ; 16 bit real mode
    org 0x7C00                      ; origine indirizzo 0000:7C00
    
    start:	
     mov ax, 0xb800	 ; text video memory
     mov ds, ax
     mov eax, 10
    write:
     cmp eax, 0
     jz end
     mov byte [eax], 'm'
     mov byte [eax+1], 0x0F    ; attrib = white on black
     sub eax, 2
     jmp write
    end:
     hlt
    
    times 510-($-$$) db 0 ; 0-padding 
    dw 0xAA55
    
    nasm -l mioboot-nobios-simple.lst -o mioboot-nobios-simple.img mioboot-nobios-simple.asm
    qemu mioboot-nobios-simple.img
    
  • Uso dei servizi del BIOS mioboot.asm
    bits 16                         ; 16 bit real mode
    org 0x7C00                      ; origine indirizzo 0000:7C00
            
    start:
            cld                     ; clears direction flag (index regs incremented)
            mov si, boot
            call message
    working:
            mov si, work
            call message
    
            call waitenter
            jmp working
    
    message:
            lodsb                   ; carica un byte da [DS:SI] in AL e inc SI
            cmp al, 0
            jz done
            mov ah, 0x0E            ; write char to screen in text mode
            mov bx, 0               ; BH page number BL foreground color
            int 0x10                ; write AL to screen (BIOS)
            jmp message
    done:   ret
    
    boot: db "Loading unuseful system...." , 10, 13, 0
    work: db "I've done my unuseful stuff!" , 10, 13, 0 
    cont: db "Hit ENTER to continue...", 10, 13, 0
    wow: db "Great! Hello world!" , 10, 13, 0
            
    waitenter: mov si, cont
               call message
               mov ah, 0
               int 0x16                ; Wait for keypress (BIOS)
               cmp al, 'm'
               jz egg
               cmp al, 'b'
               jz basic
               cmp al, 13
               jnz waitenter
               ret
    egg:       mov si, wow
               call message
               jmp waitenter
    basic:     int 0x18		; basic (BIOS)
               hlt
    
            times 510-($-$$) db 0
            dw 0xAA55
    
    nasm -l mioboot.lst -o mioboot.img mioboot.asm
    qemu mioboot.img
    # con qemu -d in_asm potete vedere (in /tmp/qemu.log) il codice eseguito dalla macchina virtuale: per la maggior parte istruzioni del BIOS 
    
  • Programma che esegue il codice letto da standard input exec.c
    #include <stdio.h>
    
    int main() {
      unsigned char buf[1024];
      void (*ptr)();
      int n;
      unsigned int eax;
    
      // leggi il codice da eseguire da standard input
      n = read(0, buf, 1024);
      // forza il codice a ritornare dalla chiamata a funzione (0xC3 = ret)
      buf[n] = '\xc3';
    
      // esegui il codice letto come se fosse una funzione
      ptr = (void(*)()) buf;
      ptr();
    
      // stampa il valore del registro EAX
      __asm__("mov %%eax, %0" : "=m"(eax));
      printf("EAX: %.8x\n", eax);
    
      return 0;
    }
    
    gcc -o exec exec.c
    echo -ne "\xB8\x11\x22\x33\x44" | ./exec
    echo -n "ciao" | ./exec
    ...
    

Lezione 2

Slide

Esercizi

fork

/* un programma che "forca" un nuovo processo */

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>

int main(void){
  int x = fork();
  if (x < 0){
      perror("Errore nella fork:");
      exit(1);
  } else {
    if (x != 0){
      while(1){
        sleep(1);
        printf("Processo padre (Figlio: %d)\n", x);
      }
    } else {
      while(1) {
       printf("Processo figlio (%d)\n", x);
       sleep(1);
      }
    }
  }
  return 0;
}

/* da compilare con un comando del tipo 'cc -o prova prova.c' */
/* Per terminare Ctrl-C */

Exit status

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char **argv) {
  int i;

  if (argc != 2)
    return -1;

  return atoi(argv[1]);
}

/* da compilare con un comando del tipo 'cc -o prova prova.c' */
/* Per verificare l'exit status: ./prova ; echo $? */

Esecuzione in sequenza e parallelo

#include <stdio.h>
#include <unistd.h>

int main(void){
  int i = 0;
  for (i=0; i<10; ++i){
    sleep(1);
    printf("%d: %d\n", getpid(), i);
  }
  return 0;
}
# In sequenza
./hello ; ./hello
# In parallelo
./hello & ./hello
echo $?

Cosa fa?

/usr/bin/touch piripacchio
while /bin/ls piripacchio; do
 /usr/bin/sleep 2
 /bin/echo ciao
done & ( /usr/bin/sleep 10 ; /bin/rm piripacchio )

Consultate il manuale!

man man
man touch
man ls
man 1 sleep # man 3 sleep è il manuale della funzione della libreria C
man echo
man rm

Uso del for e if

for i in dog cat fish; do if ls /bin/$i; then echo Trovato $i; else echo $i non trovato; fi; done
man test
for i in dog cat fish; do if test -f /bin/$i; then echo Trovato $i; else echo $i non trovato; fi; done

Link

Lezione 3

Slide

Materiale

stdout.c

/* 
   scrive st stdout(1) gli argomenti ricevuti sulla riga di comando

   utile per capire come funzionano quoting, escaping e command substitution nella shell:
   e.s. ./stdout "ciao ciao"
        ./stdout ciao ciao
        a="giallo"; b="rosso" ; ./stdout "$a $b"
        ./stdout $(ls /etc)

   compilare con: cc -o stdout stdout.c

*/

#include <stdio.h>

int main(int argc, char **argv) {
  int i;

  for (i = 0; i < argc; i++) {
    printf("%d: %s\n", i, argv[i]);
  }

  return 0;
}

stdouterr.c

/*
   scrive su stdout(1)  e stderr (2) gli argomenti ricevuti sulla riga di
   comando; l'i-esimo argomento viene scritto su stdout se i e' pari e su
   stderr se i e' dispari
   
   utile per capire come funzionano redirezione e pipe nella shell
   e.s. ./stdouterr "primo argomento" "secondo argomento" | cat
        ./stdouterr "primo argomento" "secondo argomento" 2> /tmp/2
        ./stdouterr "primo" "secondo" 2> /dev/null

   per compilare: cc -o stdouterr stdouterr.c
*/

#include <stdio.h>
#include <string.h>

int main(int argc, char **argv) {
  int i;
  char buf[2048];

  for (i = 0; i < argc; i++) {
    snprintf(buf, 2047, "%d: %s\n", i, argv[i]);
    write(i % 2 + 1, buf, strlen(buf));
  }

  return 0;
}

Esercizi online con la shell

Lezione 4

Slide

Programmi

Esempi con la syscall clone, specifica di Linux

  • Thread senza memoria condivisa threads-isolated.c

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <sched.h>

int run(void* s)
{
        int* shared = (int*)s; /* alias per comodita` */
        while (shared[0] < 10) {
                sleep(1);
                printf("Processo figlio (%d). s = %d\n", 
                       getpid(), shared[0]);
                if (!(shared[0] < 10)){
                        printf("Corsa critica!!!!\n");
                        abort();
                }
                shared[0] += 1;
        }
        return 0;
}


int main(void){
 
        int shared[2] = {0 , 0};

        /* int clone(int (*fn)(void *), 
         *           void *child_stack, 
         *           int flags,
         *           void *arg); 
         * crea una copia del chiamante (con le caratteristiche 
         * specificate da flags) e lo esegue partendo da fn */
        if (clone(run, /* il nuovo
                        * processo esegue run(shared), vedi quarto
                        * parametro */
                  malloc(4096)+4096,  /* lo stack del nuovo processo 
                                       *  (cresce verso il basso!) */
                  SIGCHLD, /* in questo caso la clone e` analoga alla fork */
                  shared) < 0){
                perror("Errore nella creazione");
                exit(1);
        } 

        if (clone(run, malloc(4096)+4096,  SIGCHLD, shared) < 0){
                perror("Errore nella creazione");
                exit(1);
        } 

        /* Isolati: ciascuno dei figli esegue 10 volte. Per il padre
         * shared[0] e` sempre 0 */

        while(1) {
                sleep(1);
                printf("Processo padre. s = %d\n", shared[0]);
        }
        return 0;
}
  • Thread con memoria condivisa threads-shared.c
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <sched.h>

int run(void* s)
{
        int* shared = (int*)s; /* alias per comodita` */
        while (shared[0] < 10) {
                sleep(1);
                printf("Processo figlio (%d). s = %d\n", 
                       getpid(), shared[0]);
                if (!(shared[0] < 10)){
                        printf("Corsa critica!!!!\n");
                        abort();
                }
                shared[0] += 1;
        }
        return 0;
}


int main(void){
 
        int shared[2] = {0 , 0};

        /* int clone(int (*fn)(void *), 
         *           void *child_stack, 
         *           int flags,
         *           void *arg); 
         * crea una copia del chiamante (con le caratteristiche 
         * specificate da flags) e lo esegue partendo da fn */
        if (clone(run, /* il nuovo
                        * processo esegue run(shared), vedi quarto
                        * parametro */
                  malloc(4096)+4096,  /* lo stack del nuovo processo 
                                       *  (cresce verso il basso!) */
                  CLONE_VM | SIGCHLD, /* la (virtual) memory e` condivisa */
                  shared) < 0){
                perror("Errore nella creazione");
                exit(1);
        } 

        if (clone(run, malloc(4096)+4096,  CLONE_VM | SIGCHLD, shared) < 0){
                perror("Errore nella creazione");
                exit(1);
        } 

        /* Memoria condivisa: i due figli nell'insieme eseguono 10 o
         * 11 volte: e` possibile una corsa critica. Il padre
         * condivide shared[0] con i figli */

        while(1) {
                sleep(1);
                printf("Processo padre. s = %d\n", shared[0]);
        }
        return 0;
}
  • Thread con memoria condivisa, mutua esclusione ottenuta con Peterson threads-peterson.c
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <sched.h>


void enter_section(int process, int* turn, int* interested)
{
        int other = 1 - process;
        interested[process] = 1;
        *turn = process;
        while  (*turn == process && interested[other]){ 
                printf("Busy waiting di %d\n", process);
        }
}

void leave_section(int process, int* interested)
{
        interested[process] = 0;
}

int run(const int p, void* s)
{
        int* shared = (int*)s; /* alias per comodita` */
        while (enter_section(p, &shared[1], &shared[2]), 
               shared[0] < 10) {
                sleep(1);
                printf("Processo figlio (%d). s = %d\n", 
                       getpid(), shared[0]);
                if (!(shared[0] < 10)){
                        printf("Corsa critica!!!!\n");
                        abort();
                }
                shared[0] += 1;
                leave_section(p, &shared[2]);
        }
        return 0;
}
  • Thread con memoria condivisa, mutua esclusione con TSL threads-tsl.c, enter.asm
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <sched.h>


void enter_section(int *s); /* in enter.asm */

void leave_section(int *s){
        *s = 0;
}

int run(const int p, void* s)
{
        int* shared = (int*)s; /* alias per comodita` */
        while (enter_section(&shared[1]), 
               shared[0] < 10) {
                sleep(rand() % 3);
                printf("Processo figlio (%d). s = %d\n", 
                       getpid(), shared[0]);
                if (!(shared[0] < 10)){
                        printf("Corsa critica!!!!\n");
                        abort();
                }
                shared[0] += 1;
                leave_section(&shared[1]);
        }
        return 0;
}

int run0(void*s){ return run(0, s); }
int run1(void*s){ return run(1, s); }
        

int main(void){
 
        int shared[4] = {0 , 0, 0, 0};

        /* int clone(int (*fn)(void *), 
         *           void *child_stack, 
         *           int flags,
         *           void *arg); 
         * crea una copia del chiamante (con le caratteristiche 
         * specificate da flags) e lo esegue partendo da fn */
        if (clone(run0, /* il nuovo
                         * processo esegue run(shared), vedi quarto
                         * parametro */
                  malloc(4096)+4096,  /* lo stack del nuovo processo 
                                       *  (cresce verso il basso!) */
                  CLONE_VM | SIGCHLD, /* la (virtual) memory e` condivisa */
                  shared) < 0){
                perror("Errore nella creazione");
                exit(1);
        } 

        if (clone(run1, malloc(4096)+4096,  CLONE_VM | SIGCHLD, shared) < 0){
                perror("Errore nella creazione");
                exit(1);
        } 

        /* Memoria condivisa: i due figli nell'insieme eseguono 10 o
         * 11 volte: e` possibile una corsa critica. Il padre
         * condivide shared[0] con i figli */

        while(shared[0] < 10) {
                sleep(1);
                printf("Processo padre. s = %d %d %d %d\n", 
                       shared[0],
                       shared[1],
                       shared[2],
                       shared[3]);
        }
        return 0;
}
section .text
global enter_section

enter_section:
        enter 0, 0         ; 0 bytes of local stack space
        mov   ebx,[ebp+8]     ; first parameter to function

spin:   lock bts dword [ebx], 0
        jc spin

        leave                   ; mov esp,ebp / pop ebp
        ret     
nasm -felf enter.asm
cc threads-tsl.c enter.o -o threads-tsl
  • Thread con memoria condivisa, mutua esclusione ottenuta con semaforo threads-sem.c
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <sched.h>
#include <semaphore.h>

sem_t S;

void enter_section(){ 
   if (sem_wait(&S) < 0){
       perror("Errore semaforo (down)");
       exit(1);
   }
}

        

void leave_section()
{
        if (sem_post(&S) < 0){
                perror("Errore semaforo (up)");
                exit(1);
        }
}

int run(const int p, void* s)
{
        int* shared = (int*) s;
        while (enter_section(), 
               *shared < 10) {
                printf("Processo figlio (%d). s = %d\n", 
                       getpid(), *shared);
                sleep(1);
                if (!(*shared < 10)){
                        printf("Corsa critica!!!!\n");
                        abort();
                }
                *shared += 1;
                leave_section();
                sched_yield();
        }
        return 0;
}

int main(void){
 
        int shared = 0;

        if (sem_init(&S, 
                     0 /* thread local semaphore */,
                     1 /* init value */
                    ) < 0){
                perror("Errore semaforo");
                exit(1);
        }

        /* int clone(int (*fn)(void *), 
         *           void *child_stack, 
         *           int flags,
         *           void *arg); 
         * crea una copia del chiamante (con le caratteristiche 
         * specificate da flags) e lo esegue partendo da fn */
        if (clone(run, /* il nuovo
                         * processo esegue run(shared), vedi quarto
                         * parametro */
                  malloc(4096)+4096,  /* lo stack del nuovo processo 
                                       *  (cresce verso il basso!) */
                  CLONE_VM | SIGCHLD, /* la (virtual) memory e` condivisa */
                  &shared) < 0){
                perror("Errore nella creazione");
                exit(1);
        } 

        if (clone(run, malloc(4096)+4096,  CLONE_VM | SIGCHLD, &shared) < 0){
                perror("Errore nella creazione");
                exit(1);
        } 

        while(shared < 10) {
                sleep(1);
                printf("Processo padre. s = %d\n", shared);
        }

        sem_destroy(&S);
        return 0;
}
cc -o threads-sem threads-sem.c -lrt

Esempi in Java

  • Creazione di thread Basic.java
class ClasseAttiva extends Thread{
    public void run(){
        while (true) {
            try {
                Thread.sleep(100);
            }
            catch(InterruptedException e){
                System.err.println(e);
            }
            System.out.println(this.getName());
        }
    }
}

public class Basic {
    public static final void main(final String[] args) {
        ClasseAttiva o1 = new ClasseAttiva();
        ClasseAttiva o2 = new ClasseAttiva();
        o1.start();
        o2.start();
        while (true){
            try {
                Thread.sleep(100);
            }
            catch(InterruptedException e){
                System.err.println(e);
            }

            System.out.println("Main thread");
        }
        
    }
}
  • Memoria condivisa Shared.java
class ClasseAttiva extends Thread{
    protected static int shared = 0;
    public void run() {
        while (true) {
            if (shared >= 10) break;
            try {
                Thread.sleep(1000);
            }
            catch(InterruptedException e){
                System.err.println(e);
            }
            if (shared >= 10){
                throw new Error("Corsa critica!!!");
            }
            System.out.println(this.getName() + " s = " + shared);
            shared += 1;
        }
    }
}



public class Shared {
    public static final void main(final String[] args) {
        ClasseAttiva o1 = new ClasseAttiva();
        ClasseAttiva o2 = new ClasseAttiva();
        o1.start();
        o2.start();
        while (true){
            try {
                Thread.sleep(1000);
            }
            catch(InterruptedException e){
                System.err.println(e);
            }

            System.out.println("Main thread");
        }
        
    }
}
  • Memoria condivisa, mutua esclusione ottenuta con synchronized, Shared2.java
class ClasseAttiva extends Thread{
    protected static int shared = 0;
    protected static Object lock = new Object();
    public void run() {
        while (true) {
            synchronized(lock){
                if (shared >= 10) break;
                try {
                    Thread.sleep(1000);
                }
                catch(InterruptedException e){
                    System.err.println(e);
                }
                if (shared >= 10){
                    throw new Error("Corsa critica!!!");
                }
                System.out.println(this.getName() + " s = " + shared);
                shared += 1;
            }
            Thread.yield(); // non necessaria, ma favorisce lo scheduling di entrambi
        }
    }
}



public class Shared2 {
    public static final void main(final String[] args) {
        ClasseAttiva o1 = new ClasseAttiva();
        ClasseAttiva o2 = new ClasseAttiva();
        o1.start();
        o2.start();
        while (true){
            try {
                Thread.sleep(1000);
            }
            catch(InterruptedException e){
                System.err.println(e);
            }

            System.out.println("Main thread");
        }
        
    }
}
  • Produttore e consumatore
class Actor extends Thread 
{
    public Actor(String nome){
        super(nome);
    }
    
    private Magazzino shared;
    public final Magazzino getShared() {
        return shared;
    }
    public final void setShared(final Magazzino newShared) {
        this.shared = newShared;
    }

}


class Produttore extends Actor {
    public Produttore(String nome, Magazzino b) {
        super(nome);
        setShared(b);
    }
    
    public void run(){
        int i = 0;
        while(true){
            System.out.println(getName() + ": Inserisco " + i + " nel buffer");
            getShared().put(i);
            i += 1;
        }
    }
}

class Consumatore extends Actor{
    public Consumatore(String nome, Magazzino b) {
        super(nome);
        setShared(b);
    }
    public void run(){
        while(true){
            int i = getShared().get();
            System.out.println(getName() + ": Estraggo " + i + " dal buffer");

        }
    }
}

class Magazzino{
    public final static int SIZE = 10;
    private int[] memory = new int[SIZE];
    private int quanti = 0;

    public final int get() {
        String n = Thread.currentThread().getName();
        synchronized(syncPC){
            while(isVuoto()){
                System.out.println(n + " ha tentato di leggere");
                try {
                    syncPC.wait();
                } catch (InterruptedException e) {
                    System.err.println(e);
                }
            }
            int ris = memory[--quanti];
            if (quanti == SIZE - 1) syncPC.notifyAll();
            System.out.println(n + " ha letto");
            return ris;
        }
    }

    public final void put(final int newMemory) {
        String n = Thread.currentThread().getName();
        synchronized(syncPC){
            while (isPieno()){
                System.out.println(n + " ha tentato di scrivere");
                try {
                    syncPC.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace(System.err);
                }
            }
            memory[quanti++] = newMemory;
            if (quanti == 1) syncPC.notifyAll();
            System.out.println(n + " ha scritto");
        }
    }

    public final boolean isVuoto() {
        return quanti == 0;
    }

    public final boolean isPieno() {
        return quanti == SIZE;
    }

    private Object syncPC = new Object();
}


public class PC {

    public static final void main(final String[] args) {
        Magazzino x = new Magazzino();
        Produttore a1 = new Produttore("Aldo", x);
        Produttore a2 = new Produttore("Alberto", x);
        Consumatore b = new Consumatore("Barbara", x);
        a1.start();
        b.start();
        a2.start();
    }

}
  • Produttore e consumatore con semafori PCSem.java
import java.util.concurrent.Semaphore;

class Actor extends Thread 
{
    public Actor(String nome){
        super(nome);
    }
    
    private Magazzino shared;
    public final Magazzino getShared() {
        return shared;
    }
    public final void setShared(final Magazzino newShared) {
        this.shared = newShared;
    }

}


class Produttore extends Actor {
    public Produttore(String nome, Magazzino b) {
        super(nome);
        setShared(b);
    }
    
    public void run(){
        int i = 0;
        while(true){
            System.out.println(getName() + ": Inserisco " + i + " nel buffer");
            getShared().put(i);
            i += 1;
        }
    }
}

class Consumatore extends Actor{
    public Consumatore(String nome, Magazzino b) {
        super(nome);
        setShared(b);
    }
    public void run(){
        while(true){
            int i = getShared().get();
            System.out.println(getName() + ": Estraggo " + i + " dal buffer");

        }
    }
}

class Magazzino{
    public final static int SIZE = 10;
    private int[] memory = new int[SIZE];
    private int quanti = 0;
    
    public final int get() {
        try{
            String n = Thread.currentThread().getName();
            pieno.acquire();
            mutex.acquire();
            int ris = memory[--quanti];
            mutex.release();
            vuoto.release();
        
            System.out.println(n + " ha letto");
            return ris;
        }
        catch(InterruptedException e){
            System.err.println(e);
            return -1;
        }
    }

    public final void put(final int newMemory) {
        try{
            String n = Thread.currentThread().getName();
            vuoto.acquire();
            mutex.acquire();
            memory[quanti++] = newMemory;
            mutex.release();
            pieno.release();
            System.out.println(n + " ha scritto");
        }
        catch(InterruptedException e){
            System.err.println(e);
        }
    }

    private static final Semaphore mutex = new Semaphore(1);
    private static final Semaphore pieno = new Semaphore(0);
    private static final Semaphore vuoto = new Semaphore(SIZE);

}


public class PCSem {

    public static final void main(final String[] args) {
        Magazzino x = new Magazzino();
        Produttore a1 = new Produttore("Aldo", x);
        Produttore a2 = new Produttore("Alberto", x);
        Consumatore b = new Consumatore("Barbara", x);
        a1.start();
        b.start();
        a2.start();
    }

}
  • Produttore e consumatore con monitor PCMon.java
import java.util.concurrent.locks.*;

class Actor extends Thread 
{
    public Actor(String nome){
        super(nome);
    }
    
    private Magazzino shared;
    public final Magazzino getShared() {
        return shared;
    }
    public final void setShared(final Magazzino newShared) {
        this.shared = newShared;
    }

}


class Produttore extends Actor {
    public Produttore(String nome, Magazzino b) {
        super(nome);
        setShared(b);
    }
    
    public void run(){
        int i = 0;
        while(true){
            System.out.println(getName() + ": Inserisco " + i + " nel buffer");
            getShared().put(i);
            i += 1;
        }
    }
}

class Consumatore extends Actor{
    public Consumatore(String nome, Magazzino b) {
        super(nome);
        setShared(b);
    }
    public void run(){
        while(true){
            int i = getShared().get();
            System.out.println(getName() + ": Estraggo " + i + " dal buffer");

        }
    }
}

class Magazzino{
    public final static int SIZE = 10;
    private int[] memory = new int[SIZE];
    private int quanti = 0;
    
    public final int get() {
        monitor.lock();
        int ris = -1;
        try{
            String n = Thread.currentThread().getName();
            while (isVuoto()){
                System.out.println(n + " ha tentato di leggere");
                empty.await();
            }
            ris = memory[--quanti];
            if (quanti == SIZE - 1) full.signal();
            System.out.println(n + " ha letto");
        } catch (InterruptedException e){
            System.err.println(e);
        } finally {
            monitor.unlock();
            return ris;
        }
    }

    public final void put(final int newMemory) {
        monitor.lock();
        try{
            String n = Thread.currentThread().getName();
            while (isPieno()){
                System.out.println(n + " ha tentato di scrivere");
                full.await();
            }
            memory[quanti++] = newMemory;
            if (quanti == 1) empty.signal();
            System.out.println(n + " ha scritto");
        } catch (InterruptedException e){
            System.err.println(e);
        } finally {
            monitor.unlock();
        }
    }

    public final boolean isVuoto() {
        return quanti == 0;
    }

    public final boolean isPieno() {
        return quanti == SIZE;
    }


    private static final Lock monitor = new ReentrantLock();
    private static final Condition empty = monitor.newCondition();
    private static final Condition full = monitor.newCondition();


}


public class PCMon {

    public static final void main(final String[] args) {
        Magazzino x = new Magazzino();
        Produttore a1 = new Produttore("Aldo", x);
        Produttore a2 = new Produttore("Alberto", x);
        Consumatore b = new Consumatore("Barbara", x);
        a1.start();
        b.start();
        a2.start();
    }

}

Lezione 5

Slide

find, archivi, segnali

Concorrenza

Programmi

Vedi Lezione 4 -- Turno 1

Lezione 6

Slide

Assembly, primi esperimenti col kernel

Permessi, Make e primi esperimenti con il kernel

Altro materiale

Lezione 7

Slide

Memorie di massa

System e kernel call

  • mykill.c
    #include <signal.h>
    #include <stdlib.h>
    
    int main(int argc, char **argv) {
            
            kill(atoi(argv[1]), 9);
            return 0;
    
    }
    
  • mykill-raw1.c
    #include <stdio.h>
    #include <stdlib.h>
    #include <ansi.h>
    #include <lib.h>
    #include <minix/ipc.h>
    
    int main(int argc, char **argv) {
      message m;
    
      printf("PID: %s SIG: %s\n", argv[1], argv[2]);
      
      m.m1_i1 = atoi(argv[1]);
      m.m1_i2 = atoi(argv[2]);
    
      printf("PID: %d SIG: %d\n", m.m1_i1, m.m1_i2);
      
      return(_syscall(MM, KILL, &m));
    }
    
  • mykill-raw2.c
    #include <stdio.h>
    #include <stdlib.h>
    #include <ansi.h>
    #include <lib.h>
    #include <minix/ipc.h>
    
    int main(int argc, char **argv) {
      message m;
      int status;
    
      printf("PID: %s SIG: %s\n", argv[1], argv[2]);
      
      m.m1_i1 = atoi(argv[1]);
      m.m1_i2 = atoi(argv[2]);
    
      printf("PID: %d SIG: %d\n", m.m1_i1, m.m1_i2);
      
    
      m.m_type = KILL;
      status = _sendrec(MM, &m);
      if (status != 0) {
            /* 'sendrec' itself failed. */
            /* XXX - strerror doesn't know all the codes */
            m.m_type = status;
      }
      if (m.m_type < 0) {
            errno = -m.m_type;
            return(-1);
      }
    
      return(0);
    }