Introducció als Sistemes Operatius

Anuncio
Introducció als Sistemes Operatius
Facultat d'Informàtica de Barcelona - UPC
16 de juny de 2000
Durada: 3 hores
Les notes es publicaran el dia 30 de juny a les 16:00 al WEB de la facultat. Per a demanar
revisió es podrà veure l'examen el dia 3 de juliol de 10:00 a 12:00 i de 17:00 a 19:00. Les notes
definitives es publicaran el dia 4 de juliol a les 16:00.
Preguntes curtes
(2.5 punts)
a) Necessitem un mecanisme que permeti a dos processos sense parentesc
comunicar-se els seus identificadors de procés. La interfície del mecanisme ha de ser
int obtenir_pid_parella(), i s’encarregarà de retornar el pid de l’altre procés quan tots
dos hagin invocat a la rutina. Es demana que dissenyis i implementis aquesta rutina sobre
UNIX. Pots suposar que només els dos processos involucrats invocaran a la rutina. (1 punt)
b) ¿En qué fase de la construcción de un fichero ejecutable intervienen los ficheros de
tipo librería (por ejemplo, libc.a en UNIX)? ¿Es posible que un mismo símbolo esté
definido en dos librerías diferentes? Justifica las respuestas. (0.5 punts)
c) Tenemos dos posibles formas de cambiar el nombre de un fichero en UNIX:
- Mediante el comando mv:
alabi_% mv f1 f2
- Mediante los comandos cp y rm:
alabi_% cp f1 f2
alabi_% rm f1
Teniendo en cuenta los recursos del sistema operativo utilizados para su ejecución,
¿qué diferencias hay entre ambos métodos? (0.5 punts)
d) Si el código fuente del ejecutable DIR es el que se muestra a continuación, ¿cuál será
el resultado de ejecutar alaba% DIR out . / /usr/bin /lib ? Justifica la respuesta (0.5
punts)
void main(int argc, char *argv[])
{ char s[80];
int i,status;
if (argc < 3) error("Parametros incorrectos",PROPI);
close(1);
if (open(argv[1], O_WRONLY|O_CREAT|O_TRUNC, 0644)<0) error("Open",SISTEMA);
for (i = 2; i < argc; i++) {
sprintf(s,"%s:\n",argv[i]);
write(1, s, strlen(s));
execlp("ls","ls","-l",argv[i],(char *)0);
wait(&status);
}
}
Telefónica
(3 punts)
Queremos escribir un programa que emule el comportamiento de una centralita de
teléfonos. Este programa, inicialmente, tendrá que crear N procesos teléfono. Cada proceso
teléfono ha de ejecutar el código que se encuentra en el ejecutable línea.
El ejecutable línea ya está implementado y simula el comportamiento de un
teléfono. Consiste en un bucle infinito en el que en cada iteración recibe una llamada, la
atiende, envía un signal SIGUSR1 a su padre y escribe por su salida estándar la información
de la llamada atendida. Esta información estará en una estructura de este tipo :
typedef struct {
int linea;
char numero[9];
int tiempo;
} llamada;
Queremos que la centralita sea inteligente, y por lo tanto su misión será doble:
1) Guardará en un fichero todas las informaciones de las llamadas.
2) Controlará que las líneas ni se saturen ni se aburran. Para este último objetivo, la
centralita controlará cada 10 minutos cuántas llamadas ha recibido. Si este número es
menor de MIN_LLAM, cancelará un telefonista mediante el signal SIGUSR2; si es mayor de
MAX_LLAM, creará uno nuevo. Ten en cuenta que al menos siempre ha de haber un
telefonista y que no puede haber más de MAX_TELEF.
Se pide que dibujes un esquema con los procesos involucrados, cómo están
comunicados y que implementes el código de la centralita.
Concurrència
(2 punts)
Volem implementar un servidor utilitzant fluxes sobre un sistema operatiu que ens
ofereix una llibreria de concurrència com la utilitzada al laboratori. Cada cop que es rebi
una petició, el servidor crearà un fluxe que l’atendrà. És a dir:
void *tractar_peticio(void *pet)
{
/* tractament d'una petició */
...
fi_fluxe(0);
}
main() /* codi del servidor */
{ peticio *pet;
inicialitzacions();
while (1) {
obtenir_peticio(pet);
crear_fluxe(tractar_peticio, pet);
}
}
a) Per a evitar saturar la màquina tractant massa peticions simultàniament, volem que
si s’estan tractant MAX_PETICIONS simultàniament, el servidor es bloquegi fins que acabi el
tractament d'alguna petició. Indica què caldria afegir al pseudocodi anterior i a on tot
justificant la resposta.
b) Volem mantenir un comptador del nombre de peticions que han estat tractades
completament. Indica què caldria afegir al pseudocodi anterior tot justificant la resposta.
c) El servidor disposa d’un nombre màxim de fitxers temporals per a fer la seva tasca
(MAX_TEMPORALS) i un camp de les peticions (pet->temporals) indica quants fitxers
temporals són necessaris per a atendre cada petició (ens asseguren que pet->temporals
sempre serà més petit que MAX_TEMPORALS). A tractar_petició tenim el següent codi, on
temporals és una variable de tipus semàfor inicialitzat a MAX_TEMPORALS:
void *tractar_peticio(peticio *pet)
{ int i;
for (i=0; i < pet->temporals; i++)
sem_wait(temporals);
/* tractament d'una petició */
for (i=0; i < pet->temporals; i++)
sem_signal(temporals);
fi_fluxe(0);
}
Pot donar algun tipus de problema aquest codi? Justifica-ho. En cas afirmatiu, indica
com es podria solucionar.
Comecocos
(2.5 punts)
Queremos implementar un juego para cuatro jugadores (llamados A, B, C y D) y que
utiliza un tablero de NxN posiciones sobre el sistema operativo UNIX.
Cada jugador estará situado en una de las esquinas del tablero, esperará un tiempo
aleatorio después del cual pondrá una de sus fichas en cada posición de una fila (o
columna). Al llegar al final de la fila (o columna), el jugador volverá a esperar un tiempo
aleatorio y pasará a la fila (o columna) siguiente, y así sucesivamente. Si al poner una ficha
sobre una posición del tablero resulta que ya está ocupada, la ficha anterior se elimina del
tablero. Ganará el juego quien, en el tiempo estipulado, tenga más fichas sobre el tablero.
Representaremos el tablero mediante un fichero de NxN bytes, las fichas con los
caracteres A, B, C y D, y cada jugador con un proceso. El sentido de avance de cada jugador
está indicado en la siguiente figura. La duración de la partida estará parametrizada.
AAAAAAAAAAA
AAA
CCCCCC
CC
CCCCCCCCCCCC
BB
BB
BB
B
B
B
B
B
B
B
D
D
D
D
D
DD
DD
DD
DD
DD
Te damos el esquema del programa principal comecocos:
void rut_alarma(int signum) { acabar_juego(); }
main (int argc, char *argv[])
{ /* Inicializaciones */
switch (pidA = fork()){
case -1: error(“fallo fork primero”);
case 0: jugador_A(...);
default: switch (pidB =fork()){
case -1: error(“fallo fork segundo”);
case 0: jugador_B(...);
default: switch (pidC = fork()){
case -1: error(“fallo fork tercero”);
case 0: jugador_C(...);
default: switch (pidD = fork()){
case -1: error(“fallo fork cuarto”);
case 0: jugador_D(...);
default: alarm(tiempo_duracion_partida);
pause();
}
}
}
}
}
Se pide que implementes los jugadores (rutinas jugador_A, jugador_B, jugador_C y
jugador_D), las inicializaciones y que declares las variables utilizadas.
Observaciones:
- Todos los jugadores escriben de uno en uno los caracteres.
- Dispones de la rutina espera(): espera a que pase un intervalo de tiempo aleatorio.
- La ejecución del juego desde la línea de comandos se hace:
alaba% comecocos fichero_tablero N tiempo_duración_partida
- El tablero es lo suficientemente grande para que no llegue ningún jugador al final
antes de que se cumpla la temporización.
Descargar