Il compito è costituito da domande chiuse e domande aperte. Non è consentito l’uso di libri, manuali, appunti., etc. Tempo massimo 2 ore.
Domande chiuse: ogni domanda corrisponde ad un punteggio di 1 punto in caso di risposta esatta, 0 in caso di risposta errata o in assenza di risposta. Solo una risposta è corretta.
1) In quale file viene definito il programma da eseguire se l’autenticazione, in fase di login, ha successo
/etc/passwd
/etc/initd
/etc/shadow
Nessuno, rappresenta un parametro della fase di autenticazione
2) Il prompt della shell è personalizzabile
Agendo sul file /etc/passwd
Modificando il programma della shell
Cambiando la shell
Modificando una variabile di ambiente della shell
3) In un sistema UNIX la Process-Table è:
Sempre residente in memoria
Swappabile su disco
E’ residente nella parte di memoria riservata ai processi utente
Nessuna delle risposte precedenti
4) Quale delle seguenti informazioni non è contenuta in un i-node:
La dimensione del file
I permessi
Il proprietario del file e gruppo
Il nome del file
5) In un sistema UNIX la system call open() di un file
Cancella il processo
Rinomina il file
Ricerca i-node corrispondente al nome del file, controlla diritti di accesso e nel caso di esito positivo carica i-node su RAM
Ricerca i-node nella tabella dei processi 6) Un hard link rappresenta
Un altro file
Un file cancellato
Una directory cancellata
7) Un link simbolico è caratterizzato da
Lo stesso i-number del file che identifica
Un pid che identifica il programma che lo ha creato
Un i-number diverso rispetto al file che identifica
Un pid che identifica il programma che ha creato il file che referenzia il link
8) Quale dei seguenti comandi consente di modificare i permessi del file “pippo” da rw- r - - r - - alla seguente maschera rw- r- - -
chmod 644 pippo
chmod o-rwx pippo
chmod u=rw pippo
chmod 740 pippo
9) Cosa succede se un processo scrive su una pipe piena tramite la system call write e il lato lettura è aperto?
Il processo va in attesa
Il processo termina
Si ottiene un messaggio di errore: “pipe overflow”
Decrementa il valore ricevuto come parametro
10) Un client invia una richiesta di connessione a un server tramite
connect(fd,0,0)
accept(fd,0,0)
sendto(fd,buffer,sizeof(buffer),&to,sizeof(struct sockaddr_in))
nessuna delle precedenti
11) A seguito di una richiesta di connessione (connect()) da parte del livello applicativo il TCP invia un segmento con:
I flag SYN e ACK attivi
Il flag SYN attivo
Il flag di reset della connessione (RST)
Domande aperte: ogni domanda corrisponde ad un punteggio variabile tra 0 e 3 punti a seconda della correttezza, completezza e sinteticità della risposta.
A.1 Descrivere gli elementi che caratterizzano un processo UNIX.
Un processo UNIX è caratterizzato da:
- Programma - Descrittore (PCB)
Il programma è uno spazio di indirizzamento virtuale costituito da:
TEXT (istruzioni)
DATA (dati inizializzati) BSS (dati non inizializzati)
HEAP (spazio per l’allocazione delle variabili dinamiche) STACK (spazio per l’attivazione delle funzioni)
Il descrittore è composto da:
process area (pid, ppid, stato, priorità, tempo cpu, exit status, uid, gid): sempre residente
user area: (registri CPU, info memoria di allocazione del processo, info su FS: ad esempio tabella file aperti)
A.2 Descrivere sinteticamente le caratteristiche dei protocolli TCP e UDP in relazione allo sviluppo di applicazioni.
Le caratteristiche dei protocolli sono:
UDP: non affidabile, connectionless, flusso di comunicazione orientato al messaggio TCP: affidabile, connection oriented, flusso di comunicazione orientato al byte
Nella scelta del protocollo da utilizzare nello sviluppo di un’applicazione distribuito va prima di tutto valutato l’aspetto legato all’affidabilità.
Si sceglie UDP se non è indispensabile affidabilità (ad esempio Streaming) oppure se è facilmente realizzabile a livello applicativo (ad esempio query DNS); TCP negli altri casi.
Secondo aspetto riguarda il modello di connessione:
- connectionless per interazioni brevi del tipo richiesta e risposta (ad esempio query DNS) - connectionoriented per interazioni lunghe (ad esempio scambio file)
Il terzo aspetto va tenuto presente nello scambio dei messaggi.
Esercizi: Ognuno dei successivi quesiti corrisponde ad un punteggio variabile a seconda della correttezza, completezza e adeguatezza della soluzione proposta. Utilizzare il linguaggio C e le system call UNIX cercando di essere chiari e strutturati, indicare anche le variabili utilizzate e nel passaggio dei parametri specificare se per valore o indirizzo.
E.1 (0-6) Scrivere un’applicazione costituita da un programma client e un programma server che girano sulla stessa macchina.
Il programma client legge da terminale una stringa (ruota su cui estrarre i numeri) fino a EOF (simulato da CTRL+D); per ciascuna stringa letta estrae 5 numeri interi, costruisce un messaggio contenente i numeri estratti + una stringa letta da terminale (ruota) e lo invia al server.
Il formato del messaggio è il seguente:
struct msg {
char ruota[20];
int num[5];
}
Il server esegue un ciclo di lettura dalla pipe fino a EOF (chiusura della pipe in scrittura da parte del client); per ogni messaggio letto scrive il contenuto su un file di testo.
Per la comunicazione tra i processi è richiesto l’uso delle named pipe. Il client e il server ricevono come parametro il nome della named pipe.
Viene fornita la funzione per generare i numeri random:
i = random(N)
che restituisce un intero casuale compreso tra 0 e N-1.
Note sintattiche
int fd_r, fd_w;
FILE *fp;
char nome_file[80], nome_pipe[80];
mknod(nome_pipe,S_IFIFO|0666,0);
fd_r = open(nome_pipe,O_RDONLY);
fd_w = open(nome_pipe,O_WRONLY);
fp = fopen(nome_file,”w”);
E.2 (0-6) Scrivere un’applicazione che prevede un client e un server che comunicano tramite il protocollo UDP. Il client invia messaggi di errore al server che provvede a scriverli su un file di testo.
1) Client
Il programma client riceve in argv[1] il nome della macchina e in argv[2] il port corrispondente al server. Il programma client legge i messaggi da terminale fino a EOF (simulato da CTRL+D) e li
Note sintattiche
struct sockaddr_in {
short sin_family; /* AF_inet */
short sin_port;
struct in_addr sin_addr;
char sun_zero[8];
};
struct hostent {
char * h_name; /* official name of host */
char **h_aliases; /* alias list */
int h_addrtype; /* host address type */
int h_length; /* length of address */
char *h_addr; /* host IP address */
};
struct hostent *server;
struct in_addr server_addr;
char hostname[40];
gethostname(hostname,40);
server = gethostbyname(hostname);
bcopy(server->h_addr, (char *)&server_addr, server->h_length);
struct sockaddr_in server_sock;
server_sock.sin_family = AF_INET;
server_sock.sin_addr = server_addr;
server_sock.sin_port = htons(2500);
bind(s,&server_sock,sizeof(server_sock));
struct sockaddr_in server_sock;
server_sock.sin_family = AF_INET;
server_sock.sin_addr.s_addr = INADDR_ANY;
server_sock.sin_port = htons(2500);
bind(s,&server_sock,sizeof(server_sock));
getsockname(s,&server_sock,sizeof(struct sockaddr_in);
int inet_aton(const char *cp, struct in_addr *inp) char *inet_ntoa(struct in_addr in);
htons() – ntohs() htonl() – ntohl()
ns = accept(s,0,0) connect(s, const struct sockaddr *to, socklen_t tolen)
recvfrom(int s, void *buf, size_t len, int flags, struct sockaddr
*from, socklen_t *fromlen)
sendto(int s, const void *buf, size_t len, int flags, const struct sockaddr *to, socklen_t tolen)