Вы находитесь на странице: 1из 25

1

PROBLEMAS DE SO2
mayo 2003

PROBLEMA 1
Tenemos un puente levadizo sobre un ro con las siguientes condiciones de utilizacin:

Los barcos tienen siempre prioridad de paso, pero para levantar el puente han de
esperar a que no haya ningn coche sobre l.

Los coches pueden utilizar el puente si no hay ningn barco pasando (en cuyo
caso el puente estar levantado) o esperando.

Escribir los algoritmos para barcos y coches utilizando semforos y monitores.

Solucin con semforos:

#include <pthread.h>
#include <semaphore.h>

#define NUM_COCHES 5
#define NUM_BARCOS 5

void bajar_puente(void) {}
void pasar(void) {}
void levantar_puente(void) {}

/*-----------------------------------------------------*/
/* Variables compartidas. */
/*-----------------------------------------------------*/
sem_t turno; /* Necesario para dar prioridad */
/* a los barcos. */
sem_t mutex1; /* Exclusin mutua entre coches.*/
sem_t mutex2; /* Exclusin mutua entre barcos.*/
sem_t libre; /* Indica si el puente est */
/* libre. */
int barcos = 0; /* Nmero de barcos intentando */
/* pasar. */
int coches = 0; /* Nmero de coches intentando */
/* pasar. */

/*-----------------------------------------------------*/
/* Cdigo de los coches. */
/*-----------------------------------------------------*/
void *coche(void *arg) {

sem_wait(&turno); /* Verificar si podemos pasar. */
sem_post(&turno);

sem_wait(&mutex1); /* Exclusin mutua en el acceso */
/* a la variable coches. */
coches++; /* Incrementar el n de coches. */
if (coches==1) /* Bloquear paso a los barcos, o*/
sem_wait(&libre); /* a los siguientes coches, si */
/* ya hubiese barcos. */
sem_post(&mutex1); /* Fin de la S.C. sobre coches. */

bajar_puente(); /* Funciones ya definidas. */
pasar();

sem_wait(&mutex1); /* S.C. para acceder a coches. */
coches--; /* Decrementar n de coches. */
if (coches==0) /* Si es el ltimo, libera el */
sem_post(&libre); /* paso a los barcos. */
sem_post(&mutex1); /* Fin de la S.C. sobre coches. */
}

/*-----------------------------------------------------*/
/* Cdigo de los barcos. */
/*-----------------------------------------------------*/
void *barco(void *arg) {

2
sem_wait(&mutex2); /* S.C. para acceder a "barcos".*/
barcos++; /* Incrementar n de barcos. */
if (barcos==1) { /* Si es el primero, bloquea el */
sem_wait(&turno); /* paso a los coches, o al resto*/
sem_wait(&libre); /* de barcos, mientras haya co- */
} /* ches. */
sem_post(&mutex2); /* Fin de la S.C. sobre barcos. */

levantar_puente();
pasar();

sem_wait(&mutex2); /* S.C. para acceder a barcos. */
barcos--; /* Decrementar n de barcos. */
if (barcos==0) { /* Si es el ltimo, libera el */
sem_post(&turno); /* paso a los coches. */
sem_post(&libre);
}
sem_post(&mutex2); /* Fin de la S.C. sobre barcos. */
}

int main(void) {
/* Identificadores de los hilos.*/
pthread_t id_barcos[NUM_BARCOS];
pthread_t id_coches[NUM_COCHES];
int i,j; /* Contador para la creacin de */
/* hilos. */

/* Inicializar todos los sem- */
/* foros como no compartidos, y */
/* con valor 1. */
sem_init(&turno, 0, 1);
sem_init(&mutex1, 0, 1);
sem_init(&mutex2, 0, 1);
sem_init(&libre, 0, 1);

/* Crear los hilos. */
i=NUM_BARCOS; j=NUM_COCHES;
while (i>0 || j>0) {
if (i>0) {
pthread_create( &id_barcos[i], NULL, barco, NULL );
i--;
}
if (j>0) {
pthread_create( &id_coches[j], NULL, coche, NULL );
j--;
}
}

/* Esperar su terminacin. */
for (i=0; i<NUM_BARCOS; i++)
pthread_join( id_barcos[i], NULL );
for (j=0; j<NUM_COCHES; j++)
pthread_join( id_coches[j], NULL );

return 0; /* Terminar. */
}

Solucin mediante monitores (pseudo-Pascal):

TYPE puente_levadizo = MONITOR;
VAR
coches, barcos, barcos_bloqueados : integer;
OkCoche, OkBarco : condition;

PROCEDURE ENTRY entrar_coche;
BEGIN
(* Para dar prioridad a los barcos, los coches se suspenden si hay algn
barco esperando. *)
IF (barcos>0) OR (barcos_bloqueados>0)
THEN OkCoche.wait;
coches := coches + 1;
OkCoche.signal; (* Liberamos en cascada al resto de coches, si los hay. *)
bajar_puente
END;

PROCEDURE ENTRY salir_coche;
BEGIN
coches := coches 1;
(* Si ya no quedan coches, dejamos pasar a los barcos. *)
3
IF coches=0 THEN OkBarco.signal
END;

PROCEDURE ENTRY entrar_barco;
BEGIN
(* Si ya hay coches pasando, el barco se suspende. *)
IF coches>0
THEN BEGIN
barcos_bloqueados := barcos_bloqueados + 1;
OkBarco.wait;
barcos_bloqueados := barcos_bloqueados 1
END;
barcos := barcos + 1;
(* Reactivamos al resto de barcos, en cascada. *)
OkBarco.signal;
levantar_puente
END;

PROCEDURE ENTRY salir_barco;
BEGIN
barcos := barcos 1;
(* Si es el ltimo barco, deja pasar a los coches. *)
IF barcos=0 THEN OkCoche.signal
END;

BEGIN (* Inicializacin del monitor. *)
barcos := 0;
coches := 0;
barcos_bloqueados := 0
END;

Solucin mediante monitores (implantacin en POSIX):

#include <pthread.h>

/*-----------------------------------------------------*/
/* Variables globales. */
/*-----------------------------------------------------*/

pthread_mutex_t mutex_monitor;
pthread_cond_t ok_barco;
pthread_cond_t ok_coche;
int coches = 0;
int barcos = 0;
int barcos_bloqueados = 0;
/*-----------------------------------------------------*/
/* Procedimientos de entrada. */
/*-----------------------------------------------------*/
void entrar_coche(void) {
pthread_mutex_lock(&mutex_monitor);
/* Damos prioridad a los barcos.*/
/* Si alguno ha pedido entrar y */
/* est suspendido, bloquear al*/
/* coche que intenta entrar. */
while ((barcos>0) || (barcos_bloqueados>0))
pthread_cond_wait(&ok_coche, &mutex_monitor);
coches++;
/* Es preferible utilizar broad-*/
/* cast en lugar de signal, pues*/
/* as garantizamos que se re- */
/* evale la condicin. Con esta*/
/* instruccin reactivamos al */
/* resto de coches. */
pthread_cond_broadcast(&ok_coche);
bajar_puente();
pthread_mutex_unlock(&mutex_monitor);
}

void salir_coche(void) {
pthread_mutex_lock(&mutex_monitor);
coches--;
if (coches==0)
pthread_cond_broadcast(&ok_barco);
pthread_mutex_unlock(&mutex_monitor);
}

void entrar_barco(void) {
pthread_mutex_lock(&mutex_monitor);
while (coches > 0) {
barcos_bloqueados++;
4
pthread_cond_wait(&ok_barco, &mutex_monitor);
barcos_bloqueados--;
}
barcos++;
pthread_cond_broadcast(&ok_barco);
levantar_puente();
pthread_mutex_unlock(&mutex_monitor);
}

void salir_barco(void) {
pthread_mutex_lock(&mutex_monitor);
barcos--;
if (barcos==0)
pthread_cond_broadcast(&ok_coche);
pthread_mutex_unlock(&mutex_monitor);
}

int main(void) {
/* En el programa principal, en-*/
/* tre otras, habra que inicia-*/
/* lizar las herramientas de */
/* sincronizacin. */
pthread_mutex_init(&mutex_monitor, NULL);
pthread_cond_init(&ok_barco, NULL);
pthread_cond_init(&ok_coche, NULL);

...
}


PROBLEMA 2
Disponemos de dos caminos que separan dos sentidos de circulacin: Norte y Sur.
Ambos caminos convergen en uno solo cuando se trata de cruzar un ro. Existen coches
que quieren pasar de norte a sur, y de sur a norte. En cualquier momento, slo pueden
atravesar el puente uno o ms coches que vayan en el mismo sentido (no se mezclan
coches que van en sentidos opuestos).

Implementar una solucin mediante semforos.

Solucin

#include <pthread.h>
#include <semaphore.h>

/*-----------------------------------------------------*/
/* Variables compartidas. */
/*-----------------------------------------------------*/
sem_t turno,libre; /* Necesarios para fijar el sen-*/
/* tido de paso. */
sem_t mutex1; /* Exclusin mutua en el acceso */
/* a la variable norte. */
sem_t mutex2; /* dem para la variable sur. */
int norte=0; /* N de vehculos en direccin */
/* norte-->sur. */
int sur=0; /* N de vehculos en direccin */
/* sur-->norte. */

/*-----------------------------------------------------*/
/* Funciones utilizadas en los hilos. */
/*-----------------------------------------------------*/
void pasar_puente(void) {}

/*-----------------------------------------------------*/
/* Hilo que representa a un vehculo en sentido N-->S */
/*-----------------------------------------------------*/
void *norte_sur(void *arg) {
sem_wait(&turno); /* Exclusin mutua a la hora de */
/* pedir el paso. */
sem_wait(&mutex1); /* S.C. para acceder a norte. */
norte++;
if (norte==1) /* El primer vehculo del norte */
sem_wait(&libre); /* no deja pasar a los del sur. */
sem_post(&mutex1); /* Fin de la S.C. de norte. */
sem_post(&turno); /* Otro hilo podr pedir paso. */

5
pasar_puente(); /* Proceder a cruzar. */

sem_wait(&mutex1); /* S.C. para acceder a norte. */
norte--;
if (norte==0) /* Si es el ltimo, permite que */
sem_post(&libre); /* los del sur pasen. */
sem_post(&mutex1); /* Fin de la S.C. de norte. */
}

/*-----------------------------------------------------*/
/* Hilo que representa a un vehculo en sentido S-->N */
/*-----------------------------------------------------*/
void *sur_norte(void *arg) {
sem_wait(&turno); /* Exclusin mutua a la hora de */
/* pedir el paso. */
sem_wait(&mutex2); /* S.C. para acceder a sur. */
sur++;
if (sur==1) /* El primer vehculo del sur no*/
sem_wait(&libre); /* deja pasar a los del norte. */
sem_post(&mutex2); /* Fin de la S.C. de sur. */
sem_post(&turno) ; /* Otro hilo podr pedir paso. */

pasar_puente(); /* Proceder a cruzar. */

sem_wait(&mutex2); /* S.C. para acceder a sur. */
sur--;
if (sur==0) /* Si es el ltimo, permite que */
sem_post(&libre); /* los del norte pasen. */
sem_post(&mutex2); /* Fin de la S.C. de sur. */
}

/*-----------------------------------------------------*/
/* En el programa principal (no mostrado) tendramos */
/* estas instrucciones de inicializacin: */
/* sem_init(&turno, 0, 1); */
/* sem_init(&libre, 0, 1); */
/* sem_init(&mutex1, 0, 1); */
/* sem_init(&mutex2, 0, 1); */
/*-----------------------------------------------------*/


PROBLEMA 3
Una barbera dispone de un silln para el corte de pelo, un barbero y una cantidad N de
sillas en la sala de espera para los clientes. Si no hay clientes que atender, el barbero se
echa una siesta. Cuando en este caso llega un cliente, tiene que despertar al barbero. Si
llegan ms clientes mientras el barbero atiende a alguien, pueden sentarse (si quedan
sillas libres en la antesala) o irse a pasear (si no quedan sillas disponibles). Mientras el
barbero atiende a un cliente, este ltimo espera detenido hasta que finalice el corte de
pelo.

El problema consiste en disear un programa adecuado para que se logre la
sincronizacin adecuada. Debe resolverse implementando en POSIX el equivalente a un
monitor, respetando la interfaz que se presenta en el ejemplo de uso siguiente:

#include <pthread.h>

typedef enum {LLENO, CORTADO} respuesta;

/*-----------------------------------------------------*/
/* Cdigo del hilo que representa a un cliente. */
/*-----------------------------------------------------*/
void *cliente(void *arg) {
respuesta res;

do {
/* Operacin del monitor. */
entrar_barberia(&res);
if (res==LLENO)
dar_una_vuelta();
} while (res!=CORTADO);
6
}

/*-----------------------------------------------------*/
/* Cdigo del hilo que representa al barbero. */
/*-----------------------------------------------------*/
void *barbero(void *arg) {
while (1) {
esperar_cliente(); /* Operacin del monitor. */
cortar_pelo(); /* No pertenece al monitor, slo*/
/* simula el corte. */
fin_corte(); /* Operacin del monitor. */
}
}


int main(void) {
int i;
pthread_t id_clientes[NUM_CLIENTES];
pthread_t id_barbero;
/* Crear clientes y barbero. */
pthread_create(&id_barbero, NULL, barbero, NULL);
for (i=0; i<NUM_CLIENTES; i++)
pthread_create(&id_clientes[i], NULL, cliente, NULL);
/* Esperar a los clientes. */
for (i=0; i<NUM_CLIENTES; i++)
pthread_join(id_clientes[i], NULL);

return 0; /* Terminar. */
}



Solucin

El cdigo que aparece a continuacin formara parte del programa mostrado en el
enunciado.


/*-----------------------------------------------------*/
/* Variables globales. */
/*-----------------------------------------------------*/
/* Para exclusin mutua en las */
/* operaciones del monitor. */
pthread_mutext_t m_monitor = PTHREAD_MUTEX_INITIALIZER;
int n_clientes = 0; /* Nmero de clientes en la bar-*/
/* bera. */
/* Sillas de espera para los */
/* clientes (basta con una con- */
/* dicin). */
pthread_cond_t silla = PTHREAD_COND_INITIALIZER;
/* Silln para el corte de pelo.*/
pthread_cond_t sillon = PTHREAD_COND_INITIALIZER;
/* Litera del barbero. */
pthread_cond_t dormir = PTHREAD_COND_INITIALIZER;

/*-----------------------------------------------------*/
/* Operaciones del monitor. */
/*-----------------------------------------------------*/
void entrar_barberia(respuesta *resp) {
pthread_mutex_lock( &m_monitor );

if (n_clientes > N)
*resp = LLENO; /* No cabe, que lo vuelva a in- */
/* tentar. */
else {
n_clientes++;
if (n_clientes==1) /* Despertar al barbero. */
pthread_cond_signal( &dormir );
/* Si no somos el primero, habr*/
7
/* que esperar. */
else pthread_cond_wait( &silla, &m_monitor );
/* Esperar a que acabe el corte.*/
pthread_cond_wait( &sillon, &m_monitor );
*resp = CORTADO;
}
pthread_mutex_unlock( &m_monitor );
}

void esperar_cliente(void) {
pthread_mutex_lock( &m_monitor );

if (n_clientes == 0) /* Echar una siesta si no hay */
/* clientes. */
pthread_cond_wait( &dormir, &m_monitor );
else /* Sino, llamar al primero. */
pthread_cond_signal( &silla );

pthread_mutex_unlock( &m_monitor);
}

void fin_corte(void) {
pthread_mutex_lock( &m_monitor );

/* Decirle al cliente que baje */
/* del silln y salga de la bar-*/
/* bera (cuando quiera). */
pthread_cond_signal( &sillon );
n_clientes--;

pthread_mutex_unlock( &m_monitor );
}
8
CUESTIONES RESUELTAS

Q1) Indique para cada una de las siguientes afirmaciones si es verdadera (V) o falsa (F).
a) Un proceso puede suspenderse al realizar una operacin V sobre un
semforo.
b) Un proceso siempre se suspende al realizar una operacin P sobre un
semforo.
c) Un proceso siempre se suspende al realizar una operacin espera (wait) sobre
una variable condicin.
d) Un proceso siempre se suspende al realizar una operacin seal (signal)
sobre una variable condicin.
e) Un proceso siempre despierta a otro proceso al realizar una operacin V sobre
un semforo.
f) Un proceso siempre despierta a otro proceso al realizar una operacin seal
(signal) sobre una variable condicin.

Solucin

Son FALSAS las afirmaciones a), b), d) y f)
Son VERDADERAS las afirmaciones c) y e)

Q2) Qu imprime por la salida estndar el siguiente programa?
#include <pthread.h>

pthread_mutex_t mutex=PTHREAD_MUTEX_INITIALIZER;


void proc1(char *arg){
pthread_mutex_lock(&mutex);
printf(arg);
pthread_mutex_unlock(&mutex);
if (strcmp(arg,2))
pthread_exit(0);
}



main (){
pthread_t id1,id2,id3;

pthread_mutex_lock(&mutex);

pthread_create(&id1,NULL,proc1,"S");
pthread_create(&id2,NULL,proc1,"O");
pthread_create(&id3,NULL,proc1,"1");

proc1("2");

pthread_mutex_unlock(&mutex);

exit(0);

}


Solucin
No imprime nada. Todos los hilos, incluyendo al principal, se suspenden en la operacin
pthread_mutex_lock(&mutex) de la funcin proc1 al estar mutex cerrado y adquirido por el hilo
principal.

Q3) Sea el siguiente programa en C y POSIX.

9
#include <semaphore.h>
#include <pthread.h>
#include <stdlib.h>
#include <stdio.h>

sem_t s,t;
int x ;

void *hilo1(void *arg) {
int i,j;
char c;
c=getchar();
x=atoi(c);/*convierte a entero*/
j=5;
for (i=1; i<=10; i++) {
j = j + x;
x = x + 1;
}
printf(j:%d\n, j );
}
void *hilo2(void *arg) {
int k, j;
k = x * 2;
for(j=1; j<=3; j++) {
k = k + j*x;
x = x - 1;
}
printf( k:%d \n, k );
}

int main(void)
{ pthread_t h1,h2;
x = 0;
sem_init(&s,0,0); /*Inicializa a 0*/
sem_init(&t,0,1); /*Inicializa a 1*/

pthread_create(&h1,NULL,hilo1,NULL);
pthread_create(&h2,NULL,hilo2,NULL);

pthread_join(h1,NULL);
pthread_join(h2,NULL);
}


Se pide completar el cdigo de los procedimientos hilo1 e hilo2, utilizando los
semforos declarados como variables globales para que los accesos sobre la variable
global x se realicen en exclusin mutua y el valor que ha de imprimir el procedimiento
hilo2 siempre aparezca en pantalla tras haberse escrito el del hilo1.

Solucin

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

sem_t s,t;
int x ;


void *hilo1(void *arg) {
int i,j;
char c;
sem_wait(&t);
c=getchar();
x=atoi(c);
j=5;
for (i=1; i<=10; i++) {
j = j + x;
x = x + 1;
}
sem_post(&t);
printf(j:%d\n, j );
sem_post(&s);
}
void *hilo2(void *arg) {
int k, j;

sem_wait(&t);
k = x * 2;
for(j=1; j<=3; j++) {
k = k + j*x;
x = x - 1;
}
sem_post(&t);
sem_wait(&s);
printf( k:%d \n, k );
}

int main(void)
{ pthread_t h1,h2 ;
x = 0;
sem_init(&s,0,0); /*Inicializa a 0*/
sem_init (&t,0,1); /Inicializa a 1*/
pthread_create(&h1,NULL,hilo1,NULL);
pthread_create(&h2,NULL,hilo2,NULL);

pthread_join(h1,NULL);
pthread_join(h2,NULL);
}

10

Q4) Suponga que un programador est implementando el mdulo de semforos en un
sistema operativo y por error ha codificado las operaciones P y V de la forma siguiente:

struct semaforo{
int contador;
PCB cola;
}
void P(semaforo *s)
{ int pidproc;
s->contador++;
if (s->contador < 0)
{
pidproc = getpid();
InsetarEnCola(s->cola,pidproc);
Reanudar(pidproc);
}
}
void V(semaforo *s)
{int pidproc;
s->contador++;
if (s->contador <= 0)
{
ExtraerDeCola(s->cola,pidproc);
Suspender(pidproc);
}
}

Indique cul es el error que ha cometido.

Solucin
Reanudar(p) debe estar en lugar de Suspender(p) y viceversa

Q5) Comente qu valores posibles tendran las variables x e y al finalizar la ejecucin de
los siguientes tres procesos concurrentes. Los valores iniciales son los siguientes: x=1,
y=4, S1=1, S2=0 y S3=1.

Proceso A

P(S2);
P(S3);
x = y * 2;
y = y + 1;
V(S3);

Proceso B

P(S1);
P(S3);
x = x + 1;
y = 8 + x;
V(S2);
V(S3);
Proceso C

P(S1);
P(S3);
x = y + 2;
y = x * 4;
V(S3);
V(S1);
Solucin
Existen dos posibles soluciones que vienen dadas por las siguientes secuencias de
ejecucin:
1) x = x + 1; y = 8 + x; x = y * 2; y = y + 1; x = 20, y = 11
2) x = y + 2; y = x * 4; x = x + 1; y = 8 + x; x = y * 2; y = y + 1; x = 30, y = 16


Q6) Sea un proceso que crea tres tipos de hilos que ejecutan las funciones Proceso1, 2 y
3, respectivamente. Cada uno de ellos ejecuta una seccin crtica SC1, SC2 y SC3 tal
como se muestra en el cdigo de las dos tablas. Ntese que existen muchos procesos de
los tres tipos 1, 2 y 3 y que todos ellos antes de acceder a su seccin crtica ejecutan una
funcin de entrada y cuando finalizan ejecutan una funcin de salida (comportamiento tipo
monitor).

#include <semaphore.h>
#include <pthread.h>
#include <stdlib.h>
#include <stdio.h>
#define NUM_HILOS 20
void EntraA();
void EntraB();
void EntraC();
void SaleA();
void SaleB();
void *Proceso2()
{
while(1)
{ SeccionRestante2;
EntraB();
SC2;
SaleB();
}
}

void *Proceso3()
11
void SaleC();

pthread_mutex_t mutex;
pthread_cond_t mutexA, mutexB, mutexC;

int nA, nB, nC;
void *Proceso1()
{
while(1)
{ SeccionRestante1;
EntraA();
SC1;
SaleA();
}
}
{
while (1)
{SeccionRestante3;
EntraC();
SC3;
SaleC();
}
}

void EntraA()
{
pthread_mutex_lock(&mutex);
while (nB>0)
pthread_cond_wait(&mutexA, &mutex);
nA=nA+1;
pthread_mutex_unlock(&mutex);
}
void SaleA()
{
pthread_mutex_lock(&mutex);
nA=nA-1;
pthread_cond_signal(&mutexA);
pthread_cond_signal(&mutexB);
pthread_cond_signal(&mutexC);
pthread_mutex_unlock(&mutex);
}
void EntraB()
{
pthread_mutex_lock(&mutex);
while((nA>0)||(nC>0))
pthread_cond_wait(&mutexB,&mutex);
mutexB.wait;
nB=nB+1;
pthread_mutex_unlock(&mutex);
}

void SaleB()
{ pthread_mutex_lock(&mutex);
nB=nB-1;
pthread_cond_signal(&mutexA);
pthread_cond_signal(&mutexB);
pthread_cond_signal(&mutexC);
pthread_mutex_unlock(&mutex);
}

void EntraC()
{
pthread_mutex_lock(&mutex);

while ((nC>0) || (nB>0))
pthread_cond_wait(&mutexC, &mutex);
nC=nC+1;
pthread_mutex_unlock(&mutex);
}

void SaleC()
{ pthread_mutex_lock(&mutex);
nC=nC-1;
pthread_cond_signal(&mutexA);
pthread_cond_signal(&mutexB);
pthread_cond_signal(&mutexC);
pthread_mutex_unlock(&mutex);
}

int main()
{ int i;
pthread_t P1,P2,P3;
nA:=0;nB:=0;nC:=0;
pthread_mutex_init(&mutez,NULL);
pthread_cond_init(&mutexA,NULL);
pthread_cond_init(&mutexB,NULL);
pthread_cond_init(&mutexC,NULL);

for(i=1;i<NUM_HILOS; i++)
{pthread_create(&P1,NULL,Proceso1,NULL);
pthread_create(&P2,NULL,Proceso2,NULL);
pthread_create(&P3,NULL,Proceso3,NULL);
}
for(i=1;i<NUM_HILOS; i++)
{pthread_join(&P1,NULL);
pthread_join(&P2,NULL);
pthread_join(&P3,NULL);
}



}


a) Indique qu tipo de sincronizacin proporciona el monitor anterior. Para ello,
conteste en la siguiente tabla en la cual debe colocar una X en el elemento (i,j)
cuando la seccin crtica de un proceso de tipo i se pueda ejecutar
concurrentemente con la seccin crtica de un proceso de tipo j.


b) Modifique los procedimientos Proceso1, Proceso2 y Proceso3 (dejando intacta
la implementacin del las funciones EntraA, EntraB, EntraC, SaleA, SaleB,
SaleC ) para conseguir el tipo de sincronizacin que se muestra en la
siguiente tabla.

12
SC1 SC2 SC3
SC1 X X ---
SC2 X --- ---
SC3 --- --- X
Solucin
a)
SC1 SC2 SC3
SC1 X -- X
SC2 -- X --
SC3 X -- --
b)
#include <semaphore.h>
#include <pthread.h>
#include <stdlib.h>
#include <stdio.h>
#define NUM_HILOS 20
void EntraA();
void EntraB();
void EntraC();
void SaleA();
void SaleB();
void SaleC();

pthread_mutex_t mutex;
pthread_cond_t mutexA, mutexB, mutexC;

int nA, nB, nC;
void *Proceso1()
{
while(1)
{ SeccionRestante1;
EntraA();
SC1;
SaleA();
}
}
void *Proceso2()
{
while(1)
{ SeccionRestante2;
EntraC();
SC2;
SaleC();
}
}

void *Proceso3()
{
while (1)
{SeccionRestante3;
EntraB();
SC3;
SaleB();
}
}







Q7)Qu llamadas al sistema utilizara para implementar la orden cp de UNIX ?.
Solucin
Fundamentalmente, open, read, write y close.

Q8) Cite tres atributos que se hereden de procesos padres a procesos hijos en UNIX.
Solucin
La imagen de memoria, el UID, el GID, la tabla de descriptores de ficheros, etc.

Q9)Cual es el mecanismo para eliminar o interrumpir la ejecucin de procesos en
UNIX?. Ponga un ejemplo.
Solucin
Las seales. Su accin por defecto es matar, aunque se les puede asociar un
manejador.
Ejemplos de seales: Pulsar la tecla CTRL-C, una divisin por cero, cualquiera de las
generadas con la orden kill.

Q10) Qu tipos de ficheros existen en UNIX?
Solucin
Regulares, directorios y especiales. Estos ltimos representan los dispositivos de E/S.
Tambin los tubos y otros mecanismos de comunicacin entre procesos son
pseudoficheros.


13
Q11) A qu ficheros estn asociados los descriptores de ficheros 0, 1 y 2 de un proceso
UNIX que se invoca de la siguiente forma:
$ mail pepe < carta 2> f
Solucin

Descriptor 0 carta
Descriptor 1 /dev/tty (la salida estndar que herede del shell)
Descriptor 2 f


Q12) Resuelva el problema de exclusin mutua de una seccin crtica utilizando la
operacin test-and-set atmica.

Solucin
int cerrojo=0; (* inicialmente FALSE *)

while test_and_set(&cerrojo) ;
SECCION CRITICA
cerrojo = 0;



Q13) Cuales son los posibles valores que tomar x como resultado de la ejecucin
concurrente de los siguientes hilos?

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

sem_t s1,s2,s3;
int x;

void *func_hilo1(void *a)
{
sem_wait(&s1);
sem_wait(&s2);
x=x+1;
sem_post(&s3);
sem_post(&s1);
sem_post(&s2);
}
void *func_hilo2(void *b)
{
sem_wait(&s2);
sem_wait(&s1);
sem_wait(&s3);
x=10*x;
sem_post(&s2);
sem_post(&s1);
}

int main()
{
pthread_t h1,h2 ;
x = 1;
sem_init(&s1,0,1); /*Inicializa a 1*/
sem_init(&s2,0,1); /*Inicializa a 1*/
sem_init(&s3,0,0); /*Inicializa a 0*/

pthread_create(&h1,NULL,func_hilo1,NULL);
pthread_create(&h2,NULL,func_hilo2,NULL);

pthread_join(h1,NULL);
pthread_join(h2,NULL);
}

Solucin
De la ejecucin del cdigo anterior se obtiene dos posibles valores de x, x=20 y x=1. En
el segundo resultado ocurre un interbloqueo.
El semforo s3, inicializado a 0, obliga a que la sentencia x= 10 * x se ejecute despus
de la sentencia x = x+1.
Si se ejecuta func_hilo1 (sin interrupcin) y, a continuacin, se ejecuta func_hilo2, el
resultado es 20. Si el hilo h1 ejecuta sem_wait(&s1) de func_hilo1 y otro hilo h2 ejecuta
14
sem_wait(&s2) de func_hilo2 antes que h1 ejecute sem_wait(&s2) de func_hilo1
entonces se tiene un interbloqueo y el resultado es x=1.

Q14) El cdigo que se proporciona a continuacin constituye una solucin al problema
de un puente levadizo.
void entrar_coche(void)
{
sem_wait(&turno);
sem_wait(&mutex1);
c = c +1;
if (c==1) sem_wait(&libre);
sem_post(&mutex1);
sem_post(&turno);

bajar_puente();
entrar_puente();
} /* fin entrar_coche*/

void salir_coche(void)
{
salir_puente;
sem_wait(&mutex1);
c = c-1;
if (c==0) sem_post(&libre);
sem_post(&mutex1);
} /*fin salir_coche*/
void entrar_barco(void)
{
sem_wait(&mutex2);
b = b+1;
if (b==1) {
sem_wait(&turno);
sem_wait(&libre);
}
sem_post(&mutex2);

levantar_puente();
entrar_puente();
} /* fin entrar_barco*/

void salir_barco(void)
{
salir_puente;
sem_wait(&mutex2);
b = b-1;
if (b==0){
sem_post(&turno);
sem_post(&libre);
}
sem_post(&mutex2);
} /*fin salir_barco*/

Las condiciones de correccin mnimas que satisface esta solucin son:
Los barcos pueden cruzar el puente cuando est levantado. Para levantarlo no debe
haber ningn coche cruzando.
Los coches pueden cruzar el puente cuando est bajado. Para bajarlo no debe haber
ningn barco cruzando.
Inicialmente, todos los semforos valen 1 y los contadores valen 0.
Conteste a las siguientes preguntas suponiendo que los semforos tienen asociada una
cola FIFO.
a) Indique el estado de las colas asociadas a los semforos y los procesos que estn
utilizando el puente despus de invocar las siguientes operaciones (se considerar que
el instante final de la operacin es cuando sta acaba o cuando el proceso que la
invoca se suspende).
C0 invoca entrar_coche.
B0 invoca entrar_barco.
C1 invoca entrar_coche.
B1 invoca entrar_barco.
b) Indique el estado de las colas asociadas a los semforos y los procesos que estn
utilizando el puente despus de invocar las siguientes operaciones:
Todos los coches / barcos que han entrado en el puente en el apartado anterior
han invocado salir_coche/ salir barco.
C2 invoca entrar_coche.
B2 invoca entrar_barco.
C3 invoca entrar_coche.
c) Qu ocurre si, hay coches en el puente, hay barcos esperando y un nuevo coche
invoca entrar_coche?.
d) Qu ocurre si hay barcos cruzando bajo el puente, hay coches esperando y un
nuevo barco invoca entrar_barco?
e) Qu ocurre si hay coches y barcos esperando y el ltimo barco bajo el puente
invoca salir_puente?
15
f) Como modificara el cdigo para que los coches pasaran de uno en uno (no necesita
reescribirlo todo).

Solucin
a) C0 pasa, B0 se detiene en libre pero coge el turno, C1 se bloquea en turno que ha
cogido B0, B1 no puede entrar porque B0 no ha liberado mutex2. Es decir:


variable contador Procesos suspendidos
mutex1 1
mutex2 -1 B1
turno -1 C1
libre -1 B0
En el puente se encuentra el proceso C0

b) Al salir C0 da paso en primer lugar a B0 al realizar P(libre), B1 pasa al liberar B0
mutex2, C2 llega y se suspende en turno, que an no ha sido liberado por los barcos,
B2 llega y pasa, C3 llega y se suspende en turno.


Variable contador Procesos suspendidos
mutex1 1
mutex2 1
turno -3 C1, C2, C3
libre 1
En el puente se encuentran B0, B1, B2

c) El coche se suspende en el semforo turno.
d) El nuevo barco cruza bajo el puente.
e) Situacin imposible.
f) En entrar_coche se suprime la llamada sem_post(&mutex1) y en salir_coche se
suprime la llamada sem_post(&mutex1). Al no liberar el semforo mutex1 hasta
despus de salir del puente, si llega un nuevo coche y tiene el turno, se suspender en
mutex1.

Q15) Dado el siguiente cdigo que se comporta como un monitor:
#include <semaphore.h>
#include <pthread.h>
#include <stdlib.h>
#include <stdio.h>

pthread_mutex_t mutex;
pthread_cond_t cola;
int cerrada;

void pasar(void) {
pthread_mutex_lock(&mutex);

if (cerrada)
pthread_cond_wait(&cola,&mutex);
pthread_cond_signal(&cola);

pthread_mutex_unlock(&mutex);
}/*fin pasar*/

void abrir(void) {
pthread_mutex_lock(&mutex);

if (cerrada) pthread_cond_signal(&cola);
cerrada = 0;

pthread_mutex_unlock(&mutex);
}
void cerrar(void) {
pthread_mutex_lock(&mutex);
cerrada = 1;
pthread_mutex_unlock(&mutex);
}/*fin cerrar*/


int main(void) {
cerrada = 1
pthread_mutex_init(&mutex,NULL);
pthread_cond_init(&cola,NULL);

:
:

} /*fin main*/


16

Conteste a las siguientes preguntas:
a) Qu efecto tendr una llamada a pasar si no se ha llamado todava a
abrir?
b) Qu efecto tendr una llamada a abrir?
c) En que diferira el comportamiento de este cdigo si no estuviese la
instruccin pthread_cond_signal(&cola) en el procedimiento pasar?

Solucin

a) Suspender al proceso en la variable condicin cola.
b) Si la barrera estaba cerrada se abre y se activan todos los procesos suspendidos.
c) En que slo pasara uno de los procesos suspendidos en cola cada vez que se abre
la barrera.

Q16) Dado el siguiente monitor:
type barrera=monitor
var cola: condition;
cerrada: boolean;

procedure entry pasar;
begin
if cerrada then cola.wait;
cola.signal
end;

procedure entry abrir;
begin
if cerrada then cola.signal;
cerrada := FALSE
end;
procedure entry cerrar;
begin
cerrada := TRUE
end;

begin
cerrada := TRUE
end.

Conteste a las siguientes preguntas:
a) Qu efecto tendr una llamada a barrera.pasar si no se ha llamado todava a
barrera.abrir?
b) Qu efecto tendr una llamada a barrera.abrir?
c) En que diferira el comportamiento de este monitor si no estuviese la instruccin
cola.signal en el procedimiento pasar?

Solucin
a) Suspender al proceso en la variable condicin cola.
b) Si la barrera estaba cerrada, se abre, y se activan todos los procesos suspendidos.
c) En que slo pasara uno de los procesos suspendidos en cola cada vez que se abra
la barrera.

Q17) Sean cuatro hilos de ejecucin H1, H2, H3 y H4, que deben iniciar la ejecucin del
cdigo que se presenta seguidamente. Estos hilos estn en la cola del planificador en ese
mismo orden y se utiliza un algoritmo FCFS. Indique cules de ellos van a finalizar su
ejecucin y en qu orden si todos los semforos presentados valen inicialmente cero y
son compartidos por todos los hilos.

H1 H2 H3 H4
P(S); V(S); V(S2); P(S2);
x = x+1; P(S); x = x+2; V(S2);
P(S3); x = 4; V(S3); P(S);
x = x2; V(S3); x = x*3; V(S);

Solucin
17
Primero en terminar: H3; segundo: H1. H2 queda suspendido en P(S), H4 queda
suspendido en P(S).

Q18) En un sistema se encuentran en ejecucin cinco procesos: P0, P1, P2, P3 y P4 que
utilizan los recursos R0, R1, R2, R3, R4 y RC. Inicialmente la cantidad de recursos de
cada tipo es la indicada en la siguiente tabla:
Recurso R0 R1 R2 R3 R4 RC
Cantidad 1 1 1 1 1 n
El perfil de ejecucin de un proceso Pi es distinto para los procesos pares e impares y es
el indicado en la tabla siguiente:
Perfil de los procesos pares Perfil de los procesos impares
while TRUE do
Peticion(RC);
Peticion(Ri);
Peticion(R((i+1) mod 5)));
UsoDeLosRecursos();
Libera(Ri);
Libera(R((i+1) mod 5));
Libera(RC);
SeccionRestante();
end while;
while TRUE do
Peticion(RC);
Peticion(R((i+1) mod 5)));
Peticion(Ri);
UsoDeLosRecursos();
Libera(Ri);
Libera(R((i+1) mod 5));
Libera(RC);
SeccionRestante();
end while;

Nota: Cada peticin de recursos solicita un solo ejemplar del recurso en concreto y
bloquea al proceso solicitante si el recurso no est disponible.
Suponiendo que n=5 Es posible que en el sistema se produzca un interbloqueo? Razone
la respuesta. En caso afirmativo describa un escenario.

Solucin
No se producir, ya que los procesos no intentan coger todos ellos los mismos recursos
en el mismo orden por lo que es imposible que se cumpla la condicin de espera
circular (La condicin de retencin y espera puede llegar a cumplirla el proceso 4, pues
puede haber obtenido el recurso 4 y despus quedarse esperando el recurso 0,
previamente concedido al proceso 0).

Q19) Describa al menos dos de las diferencias que existen entre las rdenes internas y
las rdenes externas.

Solucin
Se podran haber dado, entre otras, las siguientes:
Las rdenes internas deben ser ejecutadas directamente por el shell. En las
externas ha de crearse un proceso que ejecute un programa diferente para
realizar las acciones requeridas.
Las rdenes internas modifican directamente algn atributo del proceso
correspondiente al shell. Estos atributos sern heredados por las siguientes
rdenes externas que ejecute el shell. Ejemplos: directorio actual de trabajo (cd),
mscara de creacin de ficheros (umask), ...
El conjunto de rdenes internas est limitado tras haber implementado el shell.
Por el contrario, siempre podrn aadirse rdenes externas.

Q20) En un sistema multiprogramado existen tres procesos P1, P2, P3 que comparten
memoria y cuyas secciones crticas (exclusin mutua) vienen indicadas como
Operaciones1, Operaciones2, Operaciones3, Operaciones4, Operaciones5. Dichas
secciones crticas se han de ejecutar en el orden indicado por el nmero que acompaa a
18
su nombre y en exclusin mutua. Resuelva el problema utilizando semforos, para ello
indique el valor inicial que tendrn los semforos utilizados, as como el lugar y la
operacin sobre el semforo a realizar.
NOTA: Las dos Operaciones3 pueden ser ejecutadas concurrentemente por P2 y P3.

P1 P2 P3

Operaciones1;

Operaciones3;

Operaciones3;
Operaciones4;
Operaciones2; Operaciones5;


Solucin
Valores iniciales: Todos los semforos a cero.

P1 P2 P3

P(S1); P(S1);
Operaciones1;

Operaciones3;

P(S2);

Operaciones3;
V(S2);
Operaciones4; P(S3);
Operaciones2; V(S3); Operaciones5;
V(S1);
V(S1);

Q21) Analice el siguiente cdigo y responda a la cuestin que aparece tras l:
int contador;
pthread_mutex_t mutex =
PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t negativo =
PTHREAD_COND_INITIALIZER;

void *codigoA() {
int i;
for (i=0; i<100; i++) {
pthread_mutex_lock(&mutex);
while (contador <=0)
pthread_cond_wait(&negativo,
&mutex);
contador = contador+1;
pthread_mutex_unlock(&mutex);
}
pthread_exit(0);
}


void *codigoB() {
int i;
for (i=0; i<100; i++) {
pthread_mutex_lock(&mutex);
contador = contador-1;
pthread_cond_signal(&negativo);
pthread_mutex_unlock(&mutex);
}
pthread_exit(0);
}

main( ) {
pthread_t th_a, th_b;

contador = 0;

pthread_create(&th_a, NULL,
codigoA, NULL);
pthread_create(&th_b, NULL,
codigoB, NULL);
pthread_join(th_a, NULL);
pthread_join(th_b, NULL); exit(0);
}
Cuando la ejecucin de todos los hilos no pueda avanzar ms, indique el valor final de la
variable contador y el estado de cada hilo.

Solucin
El valor del contador ser -100. El hilo A estar suspendido en la condicin negativo,
el hilo B habr terminado y el hilo principal estar suspendido en su primer
pthread_join().

Q22) Se tienen tres procesos P1, P2 y P3 que desean ejecutar los procedimientos que
19
aparecen en los listados siguientes. En estos procedimientos, todos aquellos que
empiezan con la letra A podrn ser ejecutados concurrentemente por dos procesos
como mximo, mientras que los que empiecen con B deben ejecutarse en exclusin
mutua (slo entre los que empiecen con B, no con los empezados con A) y en el orden
que sugiere el dgito que sigue a dicha letra. Utilice semforos para proteger
adecuadamente estos procedimientos e indique el valor inicial que deber tener cada
semforo.

P1 P2 P3
A1;
B2;
A4;
B5;
B1;
B4;
A2;

B3;
A3;
B6;


Solucin
Las instrucciones a utilizar aparecen en la tabla siguiente:

P1 P2 P3
A1;
P(S1);
B2;
V(S2);
P(M);
A4;
V(M);
P(S4);
B5;
V(S5);

B1;
V(S1);
P(S3);
B4;
V(S4);
P(M);
A2;
V(M);

P(S2);
B3;
V(S3);
P(M);
A3;
V(M);
P(S5);
B6;


El valor inicial de todos los semforos ha de ser cero, excepto en el semforo M, que
tendr que valer 2.
Existen soluciones con menos semforos. Por ejemplo, donde se haya usado S4 se
habra podido usar de nuevo S1 y donde se us S5 se podra haber usado S2.

Q23) Razone por qu al crear un fichero en un sistema POSIX con la llamada
open(fichero, O_CREAT | O_TRUNC | O_WRONLY, 0666); puede darse el caso de que
dicho fichero tenga una palabra de proteccin rw-r--r--, pero no una rwx--xr-- (por
ejemplo).

Solucin
Porque todo proceso POSIX mantiene un atributo (llamado mscara de creacin de
ficheros) que indica qu derechos no deben otorgarse a los ficheros de nueva creacin
(sean del tipo que sean: regulares, directorios, etc.). Este atributo puede consultarse
con la orden umask sin argumentos y puede modificarse facilitando un argumento
cuando se emplee esa misma orden. En el ejemplo planteado, la primera palabra de
proteccin tiene menos derechos que los especificados como segundo argumento del
creat() (el valor 0666 octal implica la palabra de proteccin rw-rw-rw), cosa vlida al
emplear una mscara 022, pero la segunda palabra tiene derechos de ejecucin para
el propietario y el grupo y esos derechos no haban sido solicitados al crear el fichero.
Por tanto, ningn valor de la mscara podra haber dado como resultado tal palabra de
proteccin.

20
Q24) Dado el siguiente programa escrito en C con primitivas de sincronizacin POSIX,
donde se asume que la funcin printf escribe directamente en memoria de vdeo y, por
tanto, no llega a implicar la suspensin de los procesos (ya que no realiza una E/S que
necesite espera):
#include <pthread.h>
#include <stdio.h>

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
pthread_cond_t seg = PTHREAD_COND_INITIALIZER;
pthread_cond_t ter = PTHREAD_COND_INITIALIZER;

void *hilo1() {
pthread_mutex_lock(&mutex);
printf( Hilo 1 espera.\n );
pthread_cond_wait(&cond,&mutex);
printf( Hilo 1 avisa.\n );
pthread_cond_signal(&seg);
pthread_mutex_unlock(&mutex);
printf( "Termina hilo 1.\n" );
pthread_exit(0);
}

void *hilo2() {
pthread_mutex_lock(&mutex);
printf( Hilo 2 espera.\n );
pthread_cond_wait(&seg,&mutex);
printf( Hilo 2 avisa.\n );
pthread_cond_signal(&ter);
pthread_mutex_unlock(&mutex);
printf( "Termina hilo 2.\n" );
pthread_exit(0);
}
void *hilo3() {
pthread_mutex_lock(&mutex);
printf( Hilo 3 espera.\n );
pthread_cond_wait(&ter,&mutex);
printf( Hilo 3 liberado.\n );
pthread_mutex_unlock(&mutex);
printf( "Termina hilo 3.\n" );
pthread_exit(0);
}

void main() {
pthread_t h1,h2,h3;

pthread_create(&h1,NULL,hilo1,NULL);
pthread_create(&h2,NULL,hilo2,NULL);
pthread_create(&h3,NULL,hilo3,NULL);

printf( "Hilos creados.\n" );
pthread_mutex_lock(&mutex);
pthread_cond_signal(&cond);
printf( "Esperando hilos.\n" );
pthread_join(h1,NULL);
printf( "Hilo 1 terminado.\n" );
pthread_join(h2,NULL);
printf( "Hilo 2 terminado.\n" );
pthread_join(h3,NULL);
printf( "Hilo 3 terminado.\n" );
pthread_mutex_unlock(&mutex);
}

Indique qu se mostrar en pantalla al ejecutar el programa anterior, cuntos hilos
terminarn la ejecucin del cdigo mostrado y en qu orden. Si algn hilo no consigue
terminar indique por qu motivo no logra hacerlo. Asuma que todos los hilos tienen la
misma prioridad y se utiliza un algoritmo de planificacin FCFS.

Solucin
Salida en pantalla:
1) Hilos creados.
2) Esperando hilos.

No termina ningn hilo. El principal se queda suspendido en pthread_join(h1,NULL);
pero sigue teniendo el mutex cerrado. Los hilos h1, h2 y h3 se quedan suspendidos al
realizar su pthread_mutex_lock(&mutex); para tratar de adquirir el mutex.

Q25) Repita la cuestin anterior, pero ahora utilizando un algoritmo de planificacin por
prioridades estticas expulsivas, donde las prioridades siguen este orden h1 > h2 > h3 >
main. Es decir, h1 es el ms prioritario y main el menos.

Solucin
Salida en pantalla:
1) Hilo 1 espera.
2) Hilo 2 espera.
3) Hilo 3 espera.
4) Hilos creados.
5) Esperando hilos.

No termina ningn hilo. El hilo h1 se ha suspendido al realizar el
pthread_cond_wait(&cond, &mutex); pues la condicin todava no ha ocurrido. Lo
21
mismo sucede con los hilos h2 y h3 con sus primeras llamadas a esa misma operacin
sobre sus respectivas condiciones. No hay problemas con el mutex pues al
suspenderse en la condicin queda abierto. Finalmente, el hilo principal, tras haber
creado a todos los anteriores, se suspende en el mismo lugar que en la cuestin
anterior, por lo que todos los hilos han quedado suspendidos.

Q26) Supongamos que en POSIX no existe la actual definicin de los semforos (la que
utiliza el tipo sem_t). Complete la siguiente implementacin de semforos generales
utilizando mtex y variables condicin.

typedef struct {
int contador;
pthread_mutex_t m;
pthread_cond_t c;
} semaforo;

void inicializar_semaforo (semaforo *s, int valor) {
s->contador = valor;
pthread_mutex_init(&(s->m), NULL);
pthread_cond_init(&(s->c), NULL);
}

void V (semaforo *s) {
pthread_mutex_lock(&(s->m));
s->contador++;
pthread_cond_signal(&(s->c));
pthread_mutex_unlock(&(s->m));
}


Solucin
void P (semaforo *s) {
pthread_mutex_lock(&(s->m));
s->contador--;
if (s->contador < 0)
pthread_cond_wait(&(s->c),&(s->m));
pthread_mutex_unlock(&(s->m));
}


Q27) Sean tres procesos P1, P2 y P3 que ejecutan el cdigo que se presenta en la tabla.
Si todos los semforos tienen valor inicial 1, indique si es posible que se produzca algn
interbloqueo y por qu.

P1 P2 P3
A1;
P(s1);
P(s2);
A2;
P(s3);
A3;
V(s3);
V(s2);
V(s1);
P(s1);
B1;
P(s2);
P(s3);
B2;
V(s3);
V(s2);
V(s1);
C1;
P(s1);
C2;
P(s2);
C3;
P(s3);
C4;
V(s3);
V(s2);
V(s1);

Solucin
22
No es posible porque todos los semforos se estn pidiendo en el mismo orden en
todos los procesos. Por tanto, se cumple la regla de ordenacin global de los recursos
(en este caso las secciones protegidas por los semforos) y peticin tambin ordenada
de stos. Con esto se rompa la condicin de Coffman de espera circular explicada
dentro de las tcnicas de prevencin. Como se ha impedido que se cumpla una de las
cuatro condiciones necesarias para que aparezca un interbloqueo, ste no podr darse.

Q28) Sea el siguiente listado de un directorio en un sistema POSIX. En dicho directorio
estn disponibles todos los permisos (r, w y x) para todos los usuarios.

d-wxrw---x 2 jorge gr1 1024 May 23 10:03 prueba
-r----s--x 1 jorge gr3 4568 May 10 08:49 prog
-r-----r-- 1 jorge gr1 7846 May 09 15:01 fich1
-r---w-r-- 1 marta gr3 456 Mar 19 23:58 fich2

Indique en las casillas de la tabla siguiente si el usuario y grupo que hay en cada columna
podr completar con xito las rdenes que hay en las diferentes filas. Para ello escriba
S si puede completarse con xito o ERROR si la orden fallara. Asuma que el
ejecutable prog lee la informacin del fichero fich1 y la aade al fichero fich2 y que
todos los ficheros mencionados en el directorio prueba ya existen y tienen permisos de
lectura y escritura para todos los usuarios.

(jorge, gr1) (javi, gr1) (marta, gr2) (pedro, gr2)
ls prueba/exe
ls >> prueba/va
rm prueba/exe
prog fich1 fich2

Solucin
En la primera fila se necesita permisos de lectura y ejecucin sobre el directorio
prueba. Por ello, ninguno de los usuarios que aparecen en las cuatro columnas podr
completar esta orden con xito pues a todos les falta alguno de los dos permisos
citados.
En la segunda fila se necesitaran los permisos de lectura y ejecucin sobre el
directorio actual para poder efectuar el ls (el enunciado nos dice que todos los
usuarios poseen tales derechos) y tambin se requiere el permiso de ejecucin sobre el
directorio prueba y el de escritura sobre el fichero va (este ltimo permiso dice el
enunciado que tambin lo tienen todos los usuario). Por ello, jorge puede completar
con xito la orden, pues tiene permiso de ejecucin en el directorio prueba al ser su
propietario. El usuario javi no podr, pues est en la categora del grupo a la hora de
acceder al directorio prueba y esa clase carece de permiso de ejecucin. Por ltimo,
tanto marta como pedro pertenecen a la clase de otros y s que pueden completar
la orden, pues pueden utilizar el permiso de ejecucin.
En la tercera fila intentamos borrar un fichero presente en el directorio prueba. Para
ello se necesita el permiso de escritura y el de ejecucin sobre tal directorio. El usuario
jorge puede completar la orden, pues es el propietario y en esa clase aparecen
ambos derechos. Ninguno de los dems usuarios podr tener xito, pues javi
pertenece al grupo y en l no hay permiso de ejecucin, mientras que marta y pedro
estn en la clase de otros y en ella no tenemos permiso de escritura.
En la cuarta fila necesitaremos el permiso de ejecucin sobre el ejecutable prog. Una
vez se empieza a ejecutar el programa, como ste tiene activo el bit de SETGID, el
proceso resultante adoptar como GID efectivo gr3. Con la nueva identidad adoptada
se debe tener derecho para poder leer fich1 y poder escribir en fich2. El usuario
23
jorge no puede tener xito al intentar esta orden, ya que es el propietario y ste no
tiene permiso de ejecucin sobre el fichero prog, con lo que falla. Todos los dems
usuarios s que podrn, al menos, ejecutar dicho programa, pues estn en la categora
de otros y s tienen permiso de ejecucin. El usuario javi podr completar los otros
dos pasos con xito, pues el proceso resultante tiene identidad (javi, gr3), con lo que
puede leer fich1 (est en la clase otros y en ella tenemos permiso de lectura) y
escribir en fich2 (est en el clase grupo y en ella tenemos permiso de escritura). Al
usuario pedro le ocurre exactamente lo mismo, pudiendo completar la orden. Por
ltimo, marta tambin podra leer fich1, pero fallara a la hora de escribir sobre el
fichero fich2 pues es la propietaria de tal fichero y en dicha clase de usuarios el
fichero no tiene permiso de escritura.


CUESTIONES PROPUESTAS

C1) Sea el siguiente sistema de ficheros UNIX, donde no existen ms directorios que los
listados:

1 . 2 . 3 . 4 . 5 . 7 .
1 . . 1 . . 1 . . 2 . . 2 . . 4 . .
2 usr 4 local 6 f1.txt 7 bin2 8 cp 8 micp
3 dir 5 bin1

Indique para cada fichero el valor de su atributo nmero de enlaces:



C2) Indique si las siguientes afirmaciones son verdaderas o falsas para un sistema Unix:

La nica forma de crear un proceso nuevo (con distinto PID) es mediante
la llamada al sistema "exec".
El mandato "ps -la" se utiliza para visualizar los atributos de todos los
ficheros del directorio actual, incluidos los ocultos.
Si en un sistema de archivos UNIX existen dos entradas de directorio que
asocian dos nombres distintos a un nico nmero de nodo-i, se dice que
el fichero al que hacen referencia tiene dos enlaces fsicos.
Al redirigir la salida estndar en "cat hola > fich.txt", se debe modificar el
descriptor de fichero nmero 0 para que en lugar de referirse al fichero
especial /dev/tty se refiera a fich.txt.
Es posible que los siguientes dos nombres (o vas de acceso) absolutos
se refieran al mismo fichero: /bin/ls y /home/valencf/bin/listar


Cualquier seal que se enve a un proceso produce su terminacin.


C3) Se tienen tres procesos P1, P2 y P3 que ejecutan el siguiente cdigo (se asume que
las variables a, b y c estn compartidas por esos procesos y su valor, antes de que
ninguno de ellos empezara a ejecutar el cdigo presentado, era para todas ellas cero).

P1 P2 P3
a = 3;
c = 1; b = 2; b = b + 3;
24
c = c * 2; c = c * 2; c = c * 2;
a = a * 2; print(a,b,c); print(a,b,c);
SE PIDE:
a) Sustituya cada smbolo @, por una operacin P V sobre un semforo con el fin de
asegurar todas las condiciones siguientes:
1) La variable b debe mantener todava el valor cero cuando la a valga 6.
2) El proceso P3 debe modificar el valor de b cuando P2 ya lo haya actualizado, pero
nunca antes.
3) Debe garantizarse exclusin mutua en el acceso a la variable c.
4) Antes de que P2 y P3 muestren el valor de las variables todos los procesos han
debido concluir las modificaciones de estas variables.
b) Indique qu valor inicial deben tener todos los semforos que haya utilizado.

Valores iniciales:

P1 P2 P3
@
b = 2; @
a = 3; @ b = b + 3;
c = 1; @ c = c * 2;
c = c * 2; c = c * 2; @
a = a * 2; @ @
@ print(a,b,c); print(a,b,c);

C4) Un programador ha protegido una seccin de cdigo de su programa mediante un
semforo, utilizando una llamada a la operacin P() antes de entrar en la seccin y una
llamada a la operacin V() cuando se abandona la seccin. En ese programa se crean 10
hilos de ejecucin que van a tener acceso a esa seccin. Indique si las siguientes
afirmaciones son verdaderas o falsas:

La seccin protegida slo podr ser ejecutada por un nico hilo de
ejecucin al mismo tiempo, independientemente del valor inicial de S.
Los hilos de ejecucin podrn suspenderse al ejecutar la operacin V()
que cierra la seccin, dependiendo del valor del contador del semforo.
Los hilos de ejecucin no se suspendern en ningn caso, ya que los
semforos slo sirven para sincronizar procesos.
Dependiendo del valor al que se inicializ el semforo puede que ninguno
de los hilos tenga que suspenderse al utilizar esa seccin, incluso si todos
ellos la ejecutan a la vez.



C5) En la solucin vista en clase al problema del productor-consumidor, resuelta en el
lenguaje C utilizando POSIX Threads, se ha cometido un error al codificar las funciones
que acceden al buffer. Este error se encuentra en las siguientes lneas de cdigo:

void
poner (int id, int x) {

pthread_mutex_lock(&mutex);

while (Contador >= N)
pthread_cond_wait(&lleno,&mutex);

void
sacar (int id, int *x) {

pthread_mutex_lock(&mutex);

while (Contador >= N)
pthread_cond_wait(&vacio,&mutex);

25
V[entrada] = x;
entrada = (entrada + 1) % N;
contador = contador + 1;

pthread_cond_broadcast(&vacio);
pthread_mutex_unlock(&mutex);
}


*x = V[salida];
salida = (salida + 1) % N;
contador = contador - 1;

pthread_cond_broadcast(&lleno);
pthread_mutex_unlock(&mutex);
}


Asumiendo que se ejecutan una nica tarea productor y una nica tarea consumidor y que
el buffer inicialmente est vaco, indique si las siguientes afirmaciones son verdaderas o
falsas.



La tarea Consumidor no podr sacar nunca elementos del buffer


La tarea Consumidor puede sacar elementos del buffer incorrectos.


Puede suceder un interbloqueo que afecte a ambas tareas.
El buffer se comportar correctamente si a partir si a partir del estado
inicial se alternan estrictamente las operaciones Poner, Sacar, Poner, Sacar,
Poner, Sacar, Poner, Sacar....
Suceder un interbloqueo en cuanto ambas tareas llamen por primera vez
a sus operaciones respectivas.
La tarea Productor podr introducir elementos en el buffer cuando ste se
encuentre lleno.

Вам также может понравиться