Difference between revisions of "Lezioni Anno Accademico 2015/16"

From Sistemi Operativi
Jump to navigation Jump to search
 
(One intermediate revision by the same user not shown)
Line 1,249: Line 1,249:
  
 
== Lezione del 19 maggio 2016 ==
 
== Lezione del 19 maggio 2016 ==
 +
 +
Esercizi e chiarimenti
  
 
== CAPITOLI del corso da svolgere ==
 
== CAPITOLI del corso da svolgere ==
Line 1,278: Line 1,280:
 
* ''Tool di programmazione (make, automake ecc)''
 
* ''Tool di programmazione (make, automake ecc)''
 
* ''Differenze Linker, Loader ecc''
 
* ''Differenze Linker, Loader ecc''
* Crittografia e uso nei sistemi operativi
+
* ''Crittografia e uso nei sistemi operativi''
 
* ''Extreme C (esempi di uso (DIsuso) del linguaggio C.''
 
* ''Extreme C (esempi di uso (DIsuso) del linguaggio C.''
 
(proposte di argomenti fornite da studenti. Saranno tutti trattati, piu' avanti nel corso).
 
(proposte di argomenti fornite da studenti. Saranno tutti trattati, piu' avanti nel corso).

Latest revision as of 15:35, 21 May 2016

scrivete qui idee, riassunti dei concetti espressi, commenti approfondimenti sulle lezioni.

Lezione del 22 settembre 2015

Introduzione al corso di Sistemi Operativi.

concetti

  • Hardware vs. Software
  • Informatica
  • Scienza vs. Tecnologia
  • Informazione (vs. Dato)
  • Linguaggio
  • Elaborazione-Memorizzazione-Comunicazione
  • Algoritmo vs. Programma
  • Hacker/Hacking (vs. Cracker)
  • Maker
  • Analogico-Digitale

Lezione del 23 settembre 2015

Storia dei Sistemi.... anche operativi.

concetti

  • Architettura a livelli (Layer)
  • SO come livello di astrazione (semplificazione, portabilita')
  • SO come gestore di risorse (controllo, sicurezza, continuita' di servizio)
  • Storia le generazioni: ingranaggi->Valvole termoioniche->Transistor->Circuiti integrati->Microprocessori
  • I "ruoli" dell'informatica: ideatore, costruttore, programmatore, operatore, utente
  • Multitasking (perche' e' possibile? perche' e quando e' necessario?)
  • Interattivita'
  • TIme sharing
  • Multiuser (multiutente)
  • UNIX
  • Personal Computer (e i sistemi operativi)

Lezione del 30 settembre 2015

Il materiale per poter replicare l'esperimento sulla portabilità dei compilatori è qui.

Renzo (talk) 09:38, 3 October 2015 (CEST)

Per gli esperimenti con le macchine virtuali:

il comando per kvm è:

 kvm -m 1G -drive file=$(echo debian_wheezy*.qcow2),cache=writeback -monitor stdio
  • chi volesse provare debian hurd può scaricare l'immagine: debian-hurd-20150424.img da qui: https://www.debian.org/ports/hurd/hurd-install. Nella pagina è anche indicato come lanciare kvm (io aggiungerei -monitor stdio in fondo per avere la console di qemu-kvm).

Renzo (talk) 09:47, 3 October 2015 (CEST)

concetti

  • Conoscenze a breve, medio e lungo termine dell'informatica
  • Linguaggio dell'Hardware
  • X Virtuale (dove X rappresenta qualsiasi cosa)
  • Emulazione/Simulazione
  • virtualizzazione senza emulazione
  • Cosa e', cosa non e' e dov'e' (realmente) il sistema operativo
  • macchine virtuali
  • Distribuzione e Ambiente Operativo
  • Licenze: differenza fra Software Libero e Open Source

Lezione del 07 ottobre 2015

Ricordo che è in sospeso una domanda: "l'arduino ha un sistema operativo?"

Concetti: ripasso linguaggio C

  • Compilatori vs. Interpreti
  • Programmi vs. Script
  • Le classi di linguaggi di programmazione
  • Il "livello" dei linguaggi di programmazione
  • Cosa e', cosa non e' il Linguaggio C
  • Genesi del linguaggio C: intenzioni degli autori
  • Le vere novita' del linguaggio C

concetti: ripasso architettura

  • Modelli architetturali: von Neumann vs. Harvard
  • Gerarchia di Memoria
  • Cache
  • Indirizzi Logici, Indirizzi Fisici
  • Rilocazione

strumenti utilizzati durante la lezione

  • Arduino, hardware e sistema di sviluppo. Nelle distribuzioni debian-like c'e' il pacchetto denominato "Arduino"
 apt-get install arduino
  • Una scheda con il solo microcontrollore atmega (nella scheda in aula era un atmega168). Ho tratto ispirazione da questo articolo di tuxgraphics. Non e' necessario fare tutte le fasi iniziali di "software installation" perche' sono tutti software pacchettizzati debian. Se avete installato il pacchetto arduino tutti i cross compiler e lo strumento per caricare il firmware li trovate gia' disponibili.
  • Il programma C senza librerie e' il seguente:
typedef unsigned char uint8_t;
typedef unsigned long uint32_t;
typedef unsigned short uint16_t;

int main(void)
{
  *((volatile uint8_t *) 0x2B) = 0x00;
  *((volatile uint8_t *) 0x2A) = 0xFF;

  while (1) {
    volatile uint16_t t;
    for (t=0; t<10000; t++)
      ;
    *((volatile uint8_t *) 0x2B) += 1;
  }
  return(0);
}

per vedere il led lampeggiare occorre collegarlo (con la resistenza di limitazione della corrente) al pin 2 (porta D0) poi al pin 3 (porta D1) etc... (spostate il circuito disegnato alla porta 28 nella pagina sopra citata di tuxgraphics ai pin 2, 3 etc). NB: se volete collegare le porte GPIO o i2c di arduino o di un atmega ad un raspberry PI controllate che la tensione di lavoro dell'arduino/atmega sia 3.3v e NON 5v.

Lezione del 14 ottobre 2015

Nella pagina "esercizi ed esperimenti" ho proposto degli Esercizi di lettura di codice C. Renzo (talk) 15:43, 10 October 2015 (CEST)

temi trattati: ripasso Linguaggio C

  • Preprocessori: inclusione, compilazione condizionale macro
  • Macro vs. funzioni inline
  • Static vs. Extern
  • Static vs. Auto
  • Register

temi trattati: ripasso Architettura degli Elaboratori

  • Bus Indirizzi, Bus Dati, Gerarchie di Bus
  • Interrupt (e Trap)
  • Mascheramento degli Interrupt
  • Gestione nidificata degli interrupt
  • DMA (Direct Memory Access)

temi accennati:

  • uarm: l'emulatore per il progetto

Lezione del 21 ottobre 2015

(Correzione) Compiti a casa:

argomenti trattati

  • vettori, strutture e puntatori in C
  • il debugging: gdb
  • la funzione _start nei sistemi UNIX like.

Ecco l'esempio di funzione start minimale:

.text
.global _start

_start:
  xor %rbp, %rbp
  popq %rdi
  movq %rsp, %rsi
  andq $~15, %rsp
  call main
  //nuova interfaccia syscall
  mov %rax, %rdi
  mov $231, %rax
  syscall
  //vecchia interfaccia syscall
  //mov %eax, %ebx
  //mov $252, %eax
  //int $0x80

E il sorgente C usato nell'esperimento di debugging:

struct test {
  int a[16];
};

struct test x={{42,73,51}};

int f(struct test t) {
  return t.a[0]+t.a[1]+t.a[2];
}

int main(int argc, char *argv[]) {
  volatile int sum=f(x);
  return argc;
}

Lezione del 28 ottobre 2015

argomenti trattati

  • uARM interfaccia
  • uARM esecuzione di programmi e debug
  • cross-compilazione per uARM
  • la libreria libuarm
  • analisi della funzione tprint (polling di output)
  • debug tramite variabili e funzioni dummy
  • _start per ARM:
.global _start
_start:
  sub     lr, lr, lr
  ldr     r0, [sp]
  add     r1, sp, #4
  bl main
  mov R7, #1
  swi 0

ripasso di architettura

  • la pipeline del processore
  • Struttura del processore: Control Path, Data Path
  • CISC vs RISC

Lezione del 4 novembre 2015

argomenti trattati

  • Sistemi Real Time
  • I sistemi operativi per sistemi multiprocessore (SMP e non SMP)
  • gestione nidificata degli Interrupt nidificati
  • gli stack del kernel
  • programmed I/O (polling) vs interrupt
  • dispositivi "memory mapped" e non (come si interfacciano i dispositivi)
  • compilazione del kernel

Lezione del 11 novembre 2015

  • Visiting Lecturer: Prof. Michael Goldweber: the meaning of our O.S. project.


Lezione del 18 novembre 2015

Argomenti trattati

  • componenti del SO: gestore processi, gestore memoria primaria, gestione memoria secondaria, file system, I/O, protezione, networking
  • analisi delle system call delle prime versioni di UNIX (I manuali consultati a lezione sono qui)
  • esperimenti con la libreria pthreads. (risponde alla richiesta threads in C and how to use them...)

Esperimento (minimale) di creazione di due thread:

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

void *thread(void *arg) {
  long n=(long)arg;
  int i;
  for (i=0; i<10; i++)  {
    printf("thread %d %d\n",n,i);
    //usleep(10000);
  }
  return NULL;
}

int main(int argc, char *argv[]) {
  pthread_t t[2];
  pthread_create(&t[0], NULL, thread, (void *)0);
  pthread_create(&t[1], NULL, thread, (void *)1);
  pthread_join(t[0],NULL);
  pthread_join(t[1],NULL);
}

Race condition:

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

long tot;

void *thread(void *arg) {
  long n=(long)arg;
  int i;
  for (i=0; i<100000000; i++)
    tot  += n;
  return NULL;
}

int main(int argc, char *argv[]) {
  pthread_t t[2];
  pthread_create(&t[0], NULL, thread, (void *)-1);
  pthread_create(&t[1], NULL, thread, (void *)1);
  pthread_join(t[0],NULL);
  pthread_join(t[1],NULL);
  printf("tot = %d\n",tot);
}

Uso di istruzioni atomiche fornite da gcc:

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

long tot;

void *thread(void *arg) {
  long n=(long)arg;
  int i;
  for (i=0; i<100000000; i++)
    __sync_fetch_and_add (&tot, n);
  return NULL;
}

int main(int argc, char *argv[]) {
  pthread_t t[2];
  pthread_create(&t[0], NULL, thread, (void *)-1);
  pthread_create(&t[1], NULL, thread, (void *)1);
  pthread_join(t[0],NULL);
  pthread_join(t[1],NULL);
  printf("tot = %d\n",tot);
}

Uso di mutex:

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

long tot;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

void *thread(void *arg) {
  long n=(long)arg;
  int i;
  for (i=0; i<100000000; i++) {
    pthread_mutex_lock(&mutex);
    tot += n;
    pthread_mutex_unlock(&mutex);
  }
  return NULL;
}

int main(int argc, char *argv[]) {
  pthread_t t[2];
  pthread_create(&t[0], NULL, thread, (void *)-1);
  pthread_create(&t[1], NULL, thread, (void *)1);
  pthread_join(t[0],NULL);
  pthread_join(t[1],NULL);
  printf("tot = %d\n",tot);
}

Lezione del 25 novembre 2015

argomenti trattati

  • Presentazione della phase0 e phase1 del progetto (v. specifiche)
  • Sistemi di versioning: esempi con GIT.

Lezione del 2 dicembre 2015

Argomenti Trattati

  • Stato di avanzamento del progetto (chiarimenti e discussione su phase0 e phase1)
  • System Call: accesso ai file open/read/write/close

es. copia di file (il terzo parametro è l'ampiezza del buffer)

#include<stdio.h>
#include<fcntl.h>

int main(int argc, char *argv[]) {
  int in=open(argv[1],O_RDONLY);
  int out=open(argv[2],O_WRONLY|O_CREAT|O_TRUNC,0666);
  int n;
  int BUFSIZE=atoi(argv[3]);
  unsigned char buf[BUFSIZE];
  while ((n=read(in,buf,BUFSIZE)) != 0)
    write(out,buf,n);
  close(in);
  close(out);
}
  • System Call: gestione processi fork/execve/wait

Esempio: stampa il pid ed esegue il comando indicato nei parametri senza creare un sottoprocesso

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

extern char **environ;

int main(int argc, char *argv[]) {
  printf("%d\n",getpid());
  execve(argv[1],argv+1,environ);
  printf("err\n");
}

Esempio: una shell minimale.

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

extern char **environ;

#define BUFSIZE 1024
unsigned char cmdbuf[BUFSIZE];
char *prompt="$ ";
int main(int argc, char *argv[]) {
  int n;
  while ((write(STDOUT_FILENO,prompt,strlen(prompt)),
          n=read(STDIN_FILENO, cmdbuf, BUFSIZE)) > 0){
    char *cmdargv[1024];
    char *cmdtok=cmdbuf;
    pid_t child;
    int status;
    cmdbuf[n-1]=0;
    n=0;
    while (cmdargv[n]=strtok(cmdtok," \t")) {
      cmdtok=NULL;
      n++;
    }
    switch (child=fork()) {
      case -1:
        printf("errore fork\n");
        break;
      case 0:
        execvp(cmdargv[0],cmdargv);
        printf("errore exec\n");
        exit(-1);
      default:
        waitpid(child,&status,0);
        printf("exit status=%d\n",WEXITSTATUS(status));
        break;
    }
  }
}

La stessa shell usando la libreria s2argv-execs:

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

extern char **environ;

#define BUFSIZE 1024
unsigned char cmdbuf[BUFSIZE];
char *prompt="$ ";
int main(int argc, char *argv[]) {
  int n;
  while ((write(STDOUT_FILENO,prompt,strlen(prompt)),
          n=read(STDIN_FILENO, cmdbuf, BUFSIZE)) > 0){
    char *cmdargv[1024];
    char *cmdtok=cmdbuf;
    pid_t child;
    int status;
    cmdbuf[n-1]=0;
    n=0;
    while (cmdargv[n]=strtok(cmdtok," \t")) {
      cmdtok=NULL;
      n++;
    }
    switch (child=fork()) {
      case -1:
        printf("errore fork\n");
        break;
      case 0:
        execvp(cmdargv[0],cmdargv);
        printf("errore exec\n");
        exit(-1);
      default:
        waitpid(child,&status,0);
        printf("exit status=%d\n",WEXITSTATUS(status));
        break;
    }
  }
}

Lezione del 16 dicembre 2015

Scansione directory:

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

int notdot(const struct dirent *d) {
  return d->d_name[0] != '.';
}

int main(int argc, char * argv[]) {
  /*
  DIR *dir=opendir(argv[1]);
  struct dirent *de;
  while ((de=readdir(dir)) != NULL) 
    printf("%s\n",de->d_name);
  closedir(dir);
  */
  struct dirent **sd;
  int n=scandir(argv[1],&sd,notdot,alphasort);
  int i;
  for (i=0;i<n;i++) {
    printf("%s\n",sd[i]->d_name);
    free(sd[i]);
  }
  free(sd);
}

Ridirezione (l'output va nel file indicato come primo parametro)

#include <stdio.h>
#include <fcntl.h>

int main(int argc, char * argv[]) {
  int fd=open(argv[1],O_WRONLY|O_CREAT|O_TRUNC,0666);

  /*close(1);
  dup(fd);*/
  dup2(fd,1);

  printf("hello cruel world\n");
}

Ridirezione in pipe (come una shell implementa il comando "ls | sort -r"):

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

int main(int argc, char * argv[]) {
  int pipefd[2];
  int n;
  char buf[1024];

  pipe(pipefd);

  switch (fork()) {
    case 0: dup2(pipefd[0],0);
            close(pipefd[0]);
            close(pipefd[1]);
            execsp("sort -r");
            break;
    case -1:
            exit(1);
    default: dup2(pipefd[1],1);
             close(0);
             close(pipefd[0]);
             close(pipefd[1]);
             execsp("ls");
  }
}

Lezione del 23 febbraio 2016

Ripasso concetti I semestre.

Scheduling. Campi del Process control Block. Mode switch/Context switch.

Ruolo dello scheduler nel kernel. (esame delle attivita' svolte da un kernel durante il boot e durante il normale funzionamento).

Diagramma di Gannt

Lezione del 25 febbraio 2016

Esercitazione.

Challenge: ls -r

#include <stdio.h>
#include <stdlib.h>
#include <dirent.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>

void recscandir(char *s) {
        struct dirent **namelist;
        int n;
        n = scandir(s, &namelist, NULL, alphasort);
        if (n > 0) {
                int i;
                for (i=0; i< n; i++) {
                        char *name=namelist[i]->d_name;
                        if (strcmp(name,".")!=0 && strcmp(name,"..")!=0) {
                                int pathlen=strlen(s)+2+strlen(name);
                                char path[pathlen];
                                //struct stat buf;
                                snprintf(path,pathlen,"%s/%s",s,name);
                                printf("%s\n",path);
                                //if (lstat(path,&buf)==0 && S_ISDIR(buf.st_mode))
                                recscandir(path);
                                free(namelist[i]);
                        }
                }
                free(namelist);
        }
}

int main(int argc, char *argv[])
{
        recscandir(argc>1 ? argv[1] : ".");
        return 0;
}

Challenge: Chat con due fifo:

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

#define BUFSIZE 1024
int main(int argc, char *argv[])
{
        int fdin,fdout;
        char buf[BUFSIZE];
        int n;
        struct pollfd fds[2]={{STDIN_FILENO, POLLIN}, {0,POLLIN}};
        fdin = fds[1].fd = open(argv[2],O_RDONLY | O_NONBLOCK);
        fdout = open(argv[1],O_WRONLY);
        if (fdin < 0 || fdout < 0)
                exit(1);
        while (1) {
                poll(fds,2,-1);
                if (fds[0].revents) {
                        n=read(STDIN_FILENO, buf, BUFSIZE);
                        if (n==0)
                                break;
                        write(fdout,buf,n);
                }
                if (fds[1].revents) {
                        n=read(fdin, buf, BUFSIZE);
                        if (n==0)
                                break;
                        write(STDOUT_FILENO,buf,n);
                }
        }
        close(fdin);
        close(fdout);
}

Lezione del 01 marzo 2016

Argomenti trattati:

  • Scheduler preemptive e cooperativo
  • Scheduler FIFO: effetto convoglio (Convoy effect).
  • Scheduler Shortest Job First (SJF) e Shortest remaining time next (SRTN)
  • Scheduler Round Robin
  • Scheduler a Priorita'
  • Scheduler a Classi di Priorita'

Lezione del 03 marzo 2016

Esercitazioni/Laboratorio:

IPC tramite segnali, come trasmettere stringhe fra processi usando solo segnali POSIX.

sigsend.c

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include<signal.h>
#include<stdlib.h>
#define BUFSIZE 1024

sigset_t usr1mask;

void usr1action(int num, siginfo_t *info, void *useless) {
}

void printbin(int i,void *v)
{
        pid_t *rec=v;
        printf("%d %d\n",*rec,i?SIGUSR2:SIGUSR1);
        kill(*rec,i?SIGUSR2:SIGUSR1);
        sigsuspend(&usr1mask);
        printf("GOT ACK\n");
}

void char2bin(char x, void (*f)(int i,void *opaque),void *opaque)
{
        unsigned int i;
        for (i=0x80; i>0; i>>=1)
                f(!!(x & i),opaque);
}

int main(int argc, char *argv[]) {
        char buf[BUFSIZE];
        char *s;

        static struct sigaction sa={.sa_sigaction=usr1action,.sa_flags=SA_SIGINFO};
        sigaction(SIGUSR1,&sa,NULL);

        printf("%d\n",getpid());
        sigfillset(&usr1mask);
        sigdelset(&usr1mask,SIGINT);
        sigprocmask(SIG_SETMASK,&usr1mask,NULL);
        sigdelset(&usr1mask,SIGUSR1);
        if (argc>1) {
                pid_t receiver=atoi(argv[1]);
                while ((s=fgets(buf,BUFSIZE,stdin))!=NULL) {
                        while (*s)
                                char2bin(*s++,printbin,&receiver);
                }
        }
        printf("\n");
        return 0;
}

sigrec.c

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include<signal.h>
#include<stdlib.h>
#define BUFSIZE 1024

static int bit;
sigset_t usr12mask;
void usr12action(int num, siginfo_t *info, void *useless) {
        bit = (num == SIGUSR2);
        printf("GOT %d\n",bit);
        kill(info->si_pid, SIGUSR1);
}

int readbit(void *v)
{
        sigsuspend(&usr12mask);
        return bit;
}

int bin2char(int (*f)(void *opaque), void *opaque) {
        int i;
        int c;
        for (i=c=0; i<8; i++) {
                int n=f(opaque);
                if (n<0)
                        return -1;
                c = c<<1 | n;
        }
        return c;
}

int main(int argc, char *argv[]) {
        int c;
        static struct sigaction sa={.sa_sigaction=usr12action, .sa_flags=SA_SIGINFO};
        printf("%d\n",getpid());

        sigfillset(&usr12mask);
        sigdelset(&usr12mask,SIGINT);
        sigprocmask(SIG_SETMASK,&usr12mask,NULL);
        sigdelset(&usr12mask,SIGUSR1);
        sigdelset(&usr12mask,SIGUSR2);
        sigaction(SIGUSR1,&sa,NULL);
        sigaction(SIGUSR2,&sa,NULL);

        while ((c=bin2char(readbit,stdin)) != EOF)
                putchar(c);
        return 0;
}

Lezione del 08 marzo 2016

Gestione risorse:

  • Classi di risorse
  • assegnazione statica/dinamica
  • richiesta singola/multipla
  • richiesta bloccante/non bloccante
  • risorse prerilasciabili
  • risorse condivisibili
  • definizione formale di Deadlock
  • deadlock detection/prevention/avoidance
  • grafo di Holt
  • teorema del grafo di Holt (1 risorsa per classe)
  • riducibilita' del grafo di Holt
  • teorema del grafo di Holt (caso generale)
  • definizione di knot
  • teorema dei knot nel grafo di Holt

Lezione del 10 marzo 2016

esercitazioni mytar.c

#define _GNU_SOURCE         
#include <stdio.h>
#include <dirent.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>


int filter(const struct dirent *d) {
        if (strcmp(d->d_name,".")==0) return 0;
        if (strcmp(d->d_name,"..")==0) return 0;
        return 1;
}

int main(int argc, char *argv[]) {
        struct dirent **namelist;
        int n;
        int i;
        int pathlen1;
        int fdout;

        fdout=open(argv[2],O_CREAT|O_TRUNC|O_WRONLY,0666);
        chdir(argv[1]);
        n = scandir(".", &namelist, filter, alphasort);

        for (i=0 ; i<n; i++) {
                struct stat buf;
                if (stat(namelist[i]->d_name, &buf) == 0 && S_ISREG(buf.st_mode)) {
                        int fdin;
                        fdin=open(namelist[i]->d_name,O_RDONLY);
                        if (fdin >= 0) {
                                char *head;
                                char copybuf[1024];
                                int n;
                                asprintf(&head,"%s %ld\n", namelist[i]->d_name, buf.st_size);
                                write(fdout,head,strlen(head));
                                free(head);
                                while ((n=read(fdin, copybuf, 1024)) > 0)
                                        write(fdout, copybuf, n);
                                close(fdin);
                        }
                }
        }
}

myuntar.c

#define _GNU_SOURCE         
#include <stdio.h>
#include <dirent.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <fcntl.h>
#include <ctype.h>
#include <sys/types.h>
#include <sys/stat.h>

char buf[PATH_MAX + 20];

void filecreate(int fdin, char *name, off_t len) {
        int fdout=open(name,O_WRONLY|O_CREAT|O_TRUNC,0666);
        while (len > 0) {
                int n=read(fdin, buf, len > PATH_MAX ? PATH_MAX : len);
                write(fdout, buf, n);
                len -= n;
        }
        close(fdout);
}

int main(int argc, char *argv[]) {
        int fdin=open(argv[1],O_RDONLY);
        int n;

        while ((n=read(fdin,buf,PATH_MAX +20)) > 0) {
                char *nl=strchr(buf,'\n');
                if (nl == NULL)
                        exit(1);
                lseek(fdin, -(n - 1 - (nl - buf)), SEEK_CUR);
                //printf("n %d dn-buf %d\n",n,nl-buf);
                //printf("%d\n",lseek(fdin, 0, SEEK_CUR));
                //sleep(1);
                char *b;
                for (b=nl-1; isdigit(*b); b--);
                *b=0;
                off_t len=atol(b+1);
                //printf("%s %ld\n",buf,len);
                filecreate(fdin,buf,len);
                //lseek(fdin, len, SEEK_CUR);
        }
}

Lezione del 17 marzo 2016

Esercizi:

Respawn

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>

int main(int argc, char *argv[]) {
        int status;
        pid_t pid;
        while (1) {
                switch (pid=fork()) {
                        case 0:
                                execvp(argv[1],argv+1);
                                exit(1);
                        case -1:
                        default:
                                waitpid(pid,&status,0);
                                if (WIFEXITED(status))
                                        return WEXITSTATUS(status);
                }
        }
}

Lettura di stringhe in uno stack:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct slist {
        struct slist *next;
        char s[0];
};

struct slist *loadss(FILE *f) {
        char *buf=NULL;
        size_t len=0;
        ssize_t n;
        struct slist *head=NULL;
        while ((n=getline(&buf,&len,f)) > 0) {
                struct slist *new=malloc(sizeof(struct slist) + n + 1);
                strcpy(new->s,buf);
                new->next=head;
                head=new;
        }
        return head;
}

void printsl(struct slist *p) {
        if (p) {
                printf("%s\n",p->s);
                printsl(p->next);
        }
}

int main(char argc, char *argv[]) {
        FILE *in=fopen(argv[1],"r");
        struct slist *s=loadss(in);
        printsl(s);
}

Lezione del 22 marzo 2016

  • Deadlock recovery: Checkpoint & rollback
  • Deadlock prevention vs Avoidance
  • Algoritmo del Banchiere Monovaluta
  • Algoritmo del Banchiere Multivaluta
  • Teorema dell'algoritmo del Banchiere

Esercizi stilistici in Python

Lezione del 31 marzo 2016

System Call: memory mapping (mmap).

Python: with, scansione file con for, creazione di package

esercizi lancian:

#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>

int main(int argc, char *argv[]) {
        int n=atoi(argv[1]);
        int i;
        char *copia;
        for (i=0; i<n; i++) {
                switch (fork()) {
                        case 0:
                                asprintf(&copia,"%d",i);
                                setenv("NCOPIA",copia,1);
                                free(copia);
                                execvp(argv[2],argv+2);
                                exit(1);
                        case -1:
                                exit(1);
                        default:
                                break;
                }
        }
        for (i=0; i<n; i++) {
                int status;
                wait(&status);
        }
}

Per esercizio (puramente accademico) abbiamo provato a convertire l'array di argomenti in stringa per usare execsp.

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <s2argv.h>
#include <sys/types.h>
#include <sys/wait.h>

ssize_t argslen(char *argv[]) {
        return (*argv) ? strlen(argv[0]) + 2 + argslen(argv+1) : 0;
}

void argv2str(char *argv[], char* str) {
        while (*argv) {
                char *arg;
                for (arg=*argv; *arg; arg++, str++)
                        *str=*arg;
                *str++ = ' ';
                argv++;
        } 
        *--str = 0;
}

int main(int argc, char *argv[]) {
        int n=atoi(argv[1]);
        int i;
        char copia[14]; //large enough for MAXINT
        char argstr[argslen(argv+2)];
        argv2str(argv+2,argstr);
        //printf("%s\n",argstr);
        for (i=0; i<n; i++) {
                switch (fork()) {
                        case 0:
                                snprintf(copia,14,"%d",i);
                                setenv("NCOPIA",copia,1);
                                execsp(argstr);
                                exit(1);
                        case -1:
                                exit(1);
                        default:
                                break;
                }
        }
        for (i=0; i<n; i++) {
                int status;
                wait(&status);
        }
}

Lezione del 05 aprile 2016

Argomenti svolti: Gestione della memoria.

  • Binding
  • Allocazione
  • Partizionamento Statico/Dinamico
  • Frammentazione interna/Esterna
  • compattazione di memoria
  • Paginazione (gestione efficiente MMU tramite TLB).
  • Segmentazione
  • Paginazione+Segmentazione

Lezione del 12 aprile 2016

Argomenti svolti: Gestione della memoria

  • Linking dinamico
  • Loading dinamico
  • Memoria virtuale
  • paginazione a richiesta
  • stringa dei riferimenti
  • algoritmo di rimpiazzamento
  • algoritmo di rimpiazzamento FIFO
  • algoritmo (teorico) di rimpiazzamento MIN
  • anomalia di Belady
  • algoritmi a stack. Dimostrazione se l'algoritmo e' a stack allora non e' soggetto all'anomalia di Belady.
  • algoritmo di rimpiazzamento LRU
  • algoritmo di rimpaizzamento LFU
  • implementazioni approssimate di LRU e LFU.
  • algoritmo di second chance a.k.a. algoritmo dell'orologio.

Lezione del 14 aprile 2016

(1 ora sola al termine del seminario della Cineteca)

Installazione di librerie in spazio utente. Revisione di esercizi.

Lezione del 19 aprile 2016

Gestione della memoria.

  • Memoria Virtuale ad allocazione globale, problema del trashing
  • Calcolo del working set

Gestione della memoria secondaria

  • algoritmi di minimizzazione delle seek: Fifo, Look(ascensore), C-Look
  • RAID, in particolare Raid0, Raid1, Raid5

Lezione del 21 aprile 2016

(1 ora autogestita + 2 ore insieme)

Esercizi: Usare eventfd per trasmettere stringhe. (versione con stampe di debug).

#include <sys/eventfd.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h> 
#include <string.h> 

uint64_t endtag=0xeeeeeeeeeeeeeeee;

void evsend(int fd, int ackfd, char *s) {
        uint64_t *scan;
        uint64_t ack;
        for (scan=(uint64_t *) s; *scan; scan++) {
                printf("sending %llx on %d\n",*scan,fd);
                write(fd, scan, sizeof(uint64_t));
                read(ackfd, &ack, sizeof(uint64_t));
                printf("got ack\n");
        }
        printf("sending endtag\n");
        write(fd, &endtag, sizeof(uint64_t));
        printf("endtag sent\n");
        read(ackfd, &ack, sizeof(uint64_t));
        printf("got end ack\n");
}

void evrecv(int fd, int ackfd, char *s) {
        uint64_t *scan=(uint64_t *) s;
        uint64_t ack=1;
        while(1) {
                printf("ready to receive on %d\n",fd);
                read(fd, scan, sizeof(uint64_t));
                printf("received %llx\n",*scan);
                write(ackfd, &ack, sizeof(uint64_t));
                printf("ack sent\n");
                if (*scan == endtag) break;
                scan++;
        }
        *scan=0;
}

int main(int argc, char *argv[]) {
        int efd0, efd1;
        uint64_t c;
        static char in[255];
        uint64_t *scan;

        efd0 = eventfd(0, 0);
        efd1 = eventfd(0, 0);
        switch(fork()) {
                case 0:
                        while(1) {
                                printf("ok\n");
                                memset(in,0,255);
                                fgets(in,255,stdin);
                                evsend(efd0,efd1,in);
                                evrecv(efd1,efd0,in);
                                printf("figlio: %s\n", in);
                        }
                default:
                        while(1) {
                                evrecv(efd0,efd1,in);
                                printf("padre: %s\n", in);
                                memset(in,0,255);
                                fgets(in,255,stdin);
                                evsend(efd1,efd0,in);
                        }
        }
        close(efd0);
        close(efd1);
        return 0;
}

Lezione del 26 aprile 2016

Presentazione della fase2 del progetto jaeos2016.

Argomenti trattati:

  • File system visione utente: attributi dei file, tipi di file, organizzazione delle directory
  • FIle system visione programmatore: apertura/chiusura dei file, semantica della coerenza
  • File system visione sviluppatore: Partizionamento e struttura dei volumi
  • allocazione: contigua/concatenata/indicizzata

Lezione del 28 aprile 2016

Shell scripting:

  • evoluzioni delle shell
  • variabili locali e di ambiente
  • exit status
  • strutture di controllo (if, while, case)

Lezione del 03 maggio 2016

  • Fase 2: discussione pubblica delle specifiche.
  • File system. Gestione dello spazio inutilizzato (vettore di bit, lista concatenata).
  • Implementazione delle directory (con informazioni sui file o con puntatori ad i-node. Memorizzazione dei "nomi lunghi").
  • Esempi di FIle system: Berkeley fast file system (e derivati, e.g. ext2), FAT.
  • Metodologie per mantenere o ricreare la coerenza dei fiel system: Journaling, file system check (fsck).

Lezione del 05 maggio 2016

  • Discussione su fase 2
  • Shell scripting: find, xargs, grep, awk, sed
  • espressioni regolari.
  • Idee per la soluzione di esercizi proposti in precedenti appelli di esame.

Lezione del 10 maggio 2016

  • politiche di sicurezza e maccanismi di protezione
  • disponibilita'/integrita'/riservatezza e loro violazioni: DoS/alteration/disclosure
  • crittografia
  • funzioni a senso unico
  • singola chiave(simmetrica)/doppia chiave (asimmetrica, chiave privata/chiave pubblica)
  • DES e 3DES
  • RSA
  • simmetria di uso di RSA per autenticazione
  • attacchi attivi/passivi interni/esterni
  • punti di attacco: hardware/SO/librerie/applicazioni/utenti
  • vulnerabilita'
  • errori: buffer overflow/errori TOCTOU
  • codice maligno: cavalli di Troia (e uova di Pasqua), bombe logiche, backdoor
  • virus
  • worm (es. il worm di Morris)
  • Autenticazione (ha, sa, e')
  • password (problema attacchi vocabolario, shadow e sale)
  • challenge/response
  • PAM
  • Oggetti e Domini di accesso, la matrice degli accessi.
  • Diritti associati agli oggetti: ACL
  • Diritti associati ai domini (utenti, processi): capability
  • il problema della revoca delle capability

Lezione del 12 maggio 2016

Seminario su Plumpino.

esercizi.

Lezione del 17 maggio 2016

Esercizi e chiarimenti

Lezione del 19 maggio 2016

Esercizi e chiarimenti

CAPITOLI del corso da svolgere

(in italico i temi già trattati o parzialmente trattati)

  • Gestione risorse (deadlock)
  • Gestione memoria centrale (paginazione, segmentazione, memoria virtuale)
  • Gestione memoria secondaria
  • File system
  • Sicurezza
  • Strumenti per lo sviluppo, la portabilita' e la collaborazione (make, autotool, versioning)
  • System Call POSIX
  • Principali librerie (LibC, Pthreads, Socket...)
  • Bash (uso avanzato e scripting)
  • Python
  • uARM
  • progetto seconda fase

Argomenti proposti dagli studenti

(in Italico i temi già trattati)

  • System Call e/o esempi di uso
  • Instruction Set & Assembly
  • Memoria Centrale, Indirizzamento, Memoria Virtuale, Swapping, Traduzione Indirizzi logici in indirizzi fisici (metodi e circuiteria usata)
  • Scheduling dei processi e tipi di Scheduler, Scheduling / Schedulers
  • Linguaggi nuovi (esempio: Python)
  • Scripting
  • Tool di programmazione (make, automake ecc)
  • Differenze Linker, Loader ecc
  • Crittografia e uso nei sistemi operativi
  • Extreme C (esempi di uso (DIsuso) del linguaggio C.

(proposte di argomenti fornite da studenti. Saranno tutti trattati, piu' avanti nel corso).

  • Memory Management / Virtual Memory / Swapping Area
  • Replacement Algorithms
  • uARM further examination