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

Manual de Prcticas de Sistemas

Operativos

Curso 2010-2011
ndice general

1. Evaluacin y Calendario de Prcticas 1


1.1. Evaluacin de prcticas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1
1.2. Calendario de prcticas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2
1.3. Entrega de prcticas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2

2. Enunciado de las Prcticas 3


2.1. Prctica 1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
2.1.1. Objetivos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
2.1.2. Enunciado . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
2.2. Prctica 2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
2.2.1. Objetivos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
2.2.2. Enunciado . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
Proceso escritor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
Proceso lector . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
2.3. Prctica 3 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
2.3.1. Objetivos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
2.3.2. Enunciado . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7

3. Utilizacin y Gestin de Procesos en el Laboratorio 9


3.1. Definicin de Proceso . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
3.2. Estados de un Proceso . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
3.3. Identificacin de Procesos . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
3.4. Creacin de Procesos: fork() . . . . . . . . . . . . . . . . . . . . . . . . . . 11
3.5. Ejecucin de Procesos: execl() . . . . . . . . . . . . . . . . . . . . . . . . . 13
3.6. Compilacin . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14

4. Utilizacin de Semforos en el Laboratorio 17

5. Utilizacin de monitores en el laboratorio 21

i
ii NDICE GENERAL
Captulo 1

Evaluacin y Calendario de Prcticas

El calendario de prcticas de la asignatura recoge un total de 3 prcticas.

Prctica 1: Prctica voluntaria puntuable.

Prctica 2: Prctica voluntaria puntuable.

Prctica 3: Prctica OBLIGATORIA.

1.1. Evaluacin de prcticas


Para aprobar la parte prctica de la asignatura, es necesario entregar la prctica
obligatoria (prctica 3) en la fecha indicada, que dicha prctica funcione y responder
correctamente a algunas preguntas sobre la misma.
Opcionalmente, el alumno puede realizar las prcticas voluntarias puntuables, en-
tregndolas siempre en los plazos de entrega fijados. En el caso de que el alumno supere
la prctica obligatoria (prctica 3), se evaluarn la prcticas voluntarias (prcticas 1
y 2). En caso de una evaluacin positiva de ambas, el alumno obtendr un punto que
ser sumado a la puntuacin del examen terico siempre y cuando apruebe dicho
examen terico.
La evaluacin ser individual, y por tanto, las prcticas debern haber sido realizadas
por los dos miembros de cada grupo. Si se detectan prcticas copiadas, todos los miembros
de las parejas involucradas suspendern la asignatura.
Para aprobar la parte terica de la asignatura es necesario haber superado
la parte prctica. Es decir, slo los alumnos que superen la parte prctica (al menos
la prctica 3) podrn realizar el examen de la parte de teora. Una vez que un alumno
supera la parte prctica, queda liberado de la misma en las siguientes convocatorias. Las
prcticas voluntarias puntuables slo tienen validez en la convocatoria de Junio del curso
acadmico en el que se realizan.

1
2 CAPTULO 1. EVALUACIN Y CALENDARIO DE PRCTICAS

1.2. Calendario de prcticas


La correccin de las prcticas tendr lugar en el laboratorio, durante el horario de
prcticas del grupo, siendo imprescindible la presencia de todos los miembros del grupo
de prcticas.
En la siguiente tabla se indica: el da de comienzo de cada prctica, el da lmite de
entrega de cada prctica (a las 14:00), y el da de correccin de prcticas (en las horas
correspondientes a cada turno) para cada uno de los turnos de laboratorio.

Prctica 1 Prctica 2 Prctica 3


Turno Inicio Entrega Inicio Entrega Inicio Entrega Correccin
Lunes 28 Febrero 18 Marzo 21 Marzo 8 Abril 4 Abril 5 Mayo 9 Mayo
Martes 1 Marzo 18 Marzo 22 Marzo 8 Abril 5 Abril 5 Mayo 10 Mayo
Mircoles 2 Marzo 18 Marzo 23 Marzo 8 Abril 6 Abril 5 Mayo 11 Mayo

Adems de en el presente documento, se describir cada una de las prcticas el da de


comienzo de cada una de ellas, segn se indica en el calendario anterior. Dicha explicacin
tendr lugar al inicio de cada turno en el laboratorio LA4 de la Torre A.

1.3. Entrega de prcticas


No es necesario realizar las prcticas en el laboratorio. En la pgina Web de la asignatu-
ra, http://gssi.det.uvigo.es/ jgd/SO/SO.htm, est disponible el software necesario
para utilizar el gestor de semforos y monitores instalados en el laboratorio. Cada grupo
de laboratorio, no ms de 2 personas, dispondr de una cuenta de usuario soXX en el
servidor de laboratorios docentes. Las cuentas de usuario se pueden solicitar a los profeso-
res responsables a partir de la fecha de inicio de las prcticas (semana del 28 de Febrero).
Se recomienda leer el manual antes de abordar el desarrollo de las mismas.
Cada grupo soXX deber dejar, en el directorio /home/clave/labs/so/practicaN/soXX/
los ficheros fuentes correspondientes a la prcticaN antes de la fecha de entrega de dicha
prctica. Dichos directorios ya estn creados (no son subdirectorios dentro de la
cuenta de cada usuario), y se bloquearn una vez finalice el plazo de presentacin de
cada prctica.
Captulo 2

Enunciado de las Prcticas

2.1. Prctica 1
2.1.1. Objetivos
Entender el funcionamiento de las llamadas al sistema relacionadas con la creacin
de procesos (fork, execl, wait). Se recomienda leer la parte del manual relativa a
estas llamadas y realizar los programas de ejemplo que se incluyen (ver el captulo 3
del manual). Se recomienda tambin leer el manual on-line de dichas llamadas al
sistema (man fork, man execl, man -a wait (o man 2 wait)).

Implementar un grafo de precedencia sincronizando la ejecucin concurrente de va-


rios procesos.

2.1.2. Enunciado
(a) Implementar el grafo de precedencia de la figura 2.1 utilizando las llamadas al siste-
ma fork y wait (no utilizar waitpid). El grupo de sentencias a ejecutar en cada nodo
del grafo se simularn mediante la sentencia printf(cadena), donde cadena es la
cadena de caracteres que contiene cada nodo de la figura. La frase deber aparecer
en una nica lnea.

(b) Repetir el apartado anterior utilizando un proceso auxiliar imprime_pantalla


cuyo cdigo ser ejecutado por los procesos hijo mediante la llamada al sistema execl.
Dicho proceso deber imprimir en pantalla, mediante la sentencia printf(cadena),
la(s) cadena(s) de caracteres que reciba como argumento(s).

Los resultados obtenidos (implementando correctamente la precedencia del grafo de la


figura) en los dos apartados no deben ser los esperados. En el primer apartado se deben
obtener palabras repetidas, mientras que en el segundo stas deben verse en un orden no
permitido por el grafo pero sin repetirse. Ambas situaciones son debidas a cmo funcionan
las llamadas al sistema fork y execl. El objetivo es detectar la causa de estas dos anomalas
y entender su solucin.

3
4 CAPTULO 2. ENUNCIADO DE LAS PRCTICAS

Hola

Buenos dias tenga

y usted. Hasta

malos luego

Lucas

Figura 2.1: Grafo de Precedencia.


2.2. PRCTICA 2 5

2.2. Prctica 2
2.2.1. Objetivos
Utilizar los semforos como una herramienta de sincronizacin para acceder en ex-
clusin mutua a un recurso compartido. Para ello, se proporciona una librera que
permite la utilizacin de semforos de una manera sencilla y similar a la explicada
en teora (ver detalladamente el captulo 4 del manual).

Utilizar semforos genricos para controlar el acceso de N procesos a un recurso.

Utilizar semforos de paso para sincronizar procesos.

Utilizar el sistema de ficheros como un recurso compartido entre varios procesos,


entendiendo el funcionamiento de las llamadas al sistema fopen, fprintf, fscanf y
fclose.

2.2.2. Enunciado
Implementar, mediante la utilizacin de semforos, el problema clsico de los lectores-
escritores. Se utilizar un fichero (llamado papel.txt) con una nica palabra de texto
(mximo 20 caracteres) seguida de un carcter de final de lnea. En la solucin se debe
dar soporte a la existencia de varios procesos escritores y varios procesos lectores, teniendo
en cuenta que:

Slo se permitir leer a cuatro lectores simultneamente.

Si en el momento en que un proceso escritor intenta acceder al papel existe algn


proceso lector leyendo, el proceso escritor se demorar hasta que el papel quede libre,
o hasta que finalicen la lectura cuatro procesos lectores.

Los procesos escritores son prioritarios con respecto a los procesos lectores (cuando
el papel queda libre, siempre se da paso primero a un proceso escritor antes que a
un proceso lector).

Se podr utilizar un fichero auxiliar (llamado aux.txt) en el que se incluyan las


variables compartidas por los procesos escritores y lectores. Se valorar la utilizacin
de la informacin mnima compartida.

A continuacin se describe el funcionamiento de cada uno de los dos tipos de pro-


cesos. Se debern implementar, adems, dos procesos encargados de crear y destruir los
semforos necesarios, as como inicializar los ficheros: inic_papel y fin_papel.

Proceso escritor
Presenta en pantalla dos opciones:

1. Escribir
2. Finalizar
6 CAPTULO 2. ENUNCIADO DE LAS PRCTICAS

Cuando se seleccione la opcin Escribir, el proceso deber mostrar en pantalla la palabra


en el fichero papel.txt; esperar a que el usuario introduzca una nueva palabra; actualizar
el fichero; y volver al men anterior. Este comportamiento se repite hasta que se selecciona
la opcin Finalizar. Adems, el proceso escritor mostrar en pantalla mensajes aclaratorios
similares a los que se indican a continuacin (en el ejemplo el fichero contiene la palabra
antiguo y el escritor introduce la palabra nuevo):

Intentando acceder al fichero papel.txt...


Acceso OK
palabra actual: antiguo
palabra nueva: nuevo <ENTER>
Fichero actualizado

Proceso lector
Presenta en pantalla dos opciones:

1. Leer
2. Finalizar

Cuando se seleccione la opcin Leer, el proceso deber mostrar en pantalla el primer


carcter de la palabra en el fichero papel.txt; cada vez que se pulse la tecla <ENTER> se
mostrar la siguiente letra de dicha palabra; y una vez mostrada la ltima letra, se volver
al men inicial. Adems, el proceso lector mostrar en pantalla mensajes aclaratorios
similares a los que se indican a continuacin (en el ejemplo el fichero contiene la palabra
antiguo):

Intentando acceder al fichero papel.txt...


Acceso OK
a <se pulsa ENTER>
n <se pulsa ENTER>
t <se pulsa ENTER>
i <se pulsa ENTER>
g <se pulsa ENTER>
u <se pulsa ENTER>
o <se pulsa ENTER>
Fin de la lectura
2.3. PRCTICA 3 7

2.3. Prctica 3
2.3.1. Objetivos
Utilizar una herramienta de sincronizacin de alto nivel como son los monitores
condicionales. Para ello, se proporciona una librera que permite la utilizacin de
monitores de una manera sencilla y similar a la explicada en teora (ver detallada-
mente el captulo 5 del manual). Adems, en el manual se incluyen dos monitores
de ejemplo cuya implementacin y prueba se recomienda antes de abordar esta
prctica.

Entender las diferencias existentes entre los dos tipos de monitores vistos en teora,
en funcin del proceso elegido para continuar la ejecucin cuando se despierta un
proceso suspendido en una variable condition.

2.3.2. Enunciado
En este problema se deber simular mediante la utilizacin de un monitor BUFFER
la gestin de un buffer de N posiciones con las siguientes caractersticas:

En el buffer coexisten dos tipos de elementos t1 y t2 .

Existen 2 tipos de procesos productores: productores que producen nicamente ele-


mentos de tipo t1 y productores que producen nicamente elementos de tipo t2 . Cada
proceso productor intenta introducir un nmero 1 n N de elementos del tipo
correspondiente. Dichos procesos esperan sin introducir ningn elemento hasta
que puedan introducir la totalidad de elementos deseados.

Igualmente, existen 2 tipos de procesos consumidores: consumidores que consumen


nicamente elementos de tipo t1 y consumidores que consumen nicamente elemen-
tos de tipo t2 . Cada proceso consumidor intenta consumir un nico elemento del
tipo correspondiente, esperando hasta que pueda consumir el elemento deseado.

Los procesos productores no conocen el tipo de los elementos que introducen en el


buffer.

Cada proceso productor recibir como parmetro el tipo correspondiente (1 o 2) y


el nmero de elementos a producir.

Para que un proceso consumidor pueda averiguar el tipo de los elementos que hay en
el buffer es necesario que dichos elementos sean extrados. Si un proceso consumidor
extrae un elemento del buffer y ste no es de su tipo debe introducir de nuevo dicho
elemento en el buffer e intentarlo con el siguiente elemento. Si no le sirve ningn
elemento deber esperar hasta que pueda consumir el elemento deseado.

Suponga que existen las siguientes funciones internas del monitor:

introducir_elemento(): introduce un elemento al final del buffer.


8 CAPTULO 2. ENUNCIADO DE LAS PRCTICAS

extraer_elemento(): extrae el primer elemento del buffer indicando el tipo del


mismo.

Cada proceso consumidor recibir como parmetro el tipo correspondiente (1 o 2).

Los procesos productores acceden al buffer en orden FIFO. Es decir, un proceso


productor no puede ser adelantado por otros procesos productores.

Los procesos consumidores acceden al buffer en orden FIFO. Sin embargo, un proceso
consumidor de tipo t1 (t2 ) puede ser adelantado por procesos consumidores de tipo
t2 (t1 ) cuando en el buffer no hay elementos del tipo t1 (t2 ).

Se implementarn dos procesos encargados de crear y destruir el monitor: crear_buffer


y fin_buffer.

Ejemplos de ejecucin:

> productor 1 4
He producido 4 elementos.
Esperando a poder introducir los elementos en el buffer...
Elementos introducidos. Hay 12 elementos en total.

> consumidor 2
Esperando a retirar un elemento de tipo 2...
Elemento de tipo 2 retirado y consumido. Quedan 11 elementos en total.
Captulo 3

Utilizacin y Gestin de Procesos en el


Laboratorio

3.1. Definicin de Proceso

Un programa es una secuencia de instrucciones escrita en un lenguaje de progra-


macin. Un proceso es una instancia de ejecucin de un programa. Un programa es
un concepto esttico, mientras que un proceso es un concepto dinmico. En un entorno
multiusuario, es posible que varios usuarios ejecuten el mismo programa, obteniendo un
proceso distinto por cada ejecucin.

3.2. Estados de un Proceso

En un entorno multitarea coexisten varios procesos que se ejecutan de manera entre-


lazada (un nico procesador). Sin embargo, algunos procesos se encuentran esperando
eventos, por ejemplo esperando a que el usuario pulse una tecla, dicha espera se debe
realizar de manera que se perjudique lo menos posible al resto de procesos, con los que se
comparte la CPU.

Si se realiza espera activa, cada vez que el sistema operativo le asigne la CPU a
dicho proceso, ste mirar el teclado a ver si se ha pulsado una tecla, y esto lo repetir
hasta que dicho evento se produzca. Durante todo ese tiempo, el proceso est consumiendo
innecesariamente CPU. Para evitar la espera activa, los procesos se suspenden a espera
de eventos, de manera que dichos procesos no entren en el reparto de la CPU.

A continuacin se enumeran los distintos estados en los que se puede encontrar un


proceso:

Preparados (R): Conjunto de procesos que pueden ejecutarse en este momento,


es decir, disponen de todos los recursos necesarios para poder ejecutarse, salvo la
CPU. El sistema operativo les ir asignando la CPU a cada uno de ellos.

9
10CAPTULO 3. UTILIZACIN Y GESTIN DE PROCESOS EN EL LABORATORIO

Ejecutando (O): El proceso ocupa actualmente la CPU: Slo uno de los procesos
preparados se estar ejecutando en cada momento (monoprocesador).
Suspendidos (S): A dichos procesos les falta, adems de la CPU, algn recurso
para poder ejecutarse, entendindose por recurso un dispositivo, un dato, etc. Los
procesos suspendidos estn esperando a que ocurra algn evento para poder acceder
al recurso que necesitan. Estos procesos no entran en el reparto de la CPU, evitando
as la espera activa. Cuando se produce el evento esperado, dicho proceso pasar a
estar preparado.
Parados (T): Son procesos que tampoco entran en el reparto de la CPU, pero
que no estn suspendidos a la espera de eventos, sino que han sido parados en su
ejecucin. Para salir de dicho estado hay que mandarles continuar, volviendo as a
estar preparados.
Zombies (Z): Cuando un proceso finaliza, se lo comunica a su proceso padre (el
proceso que lo cre). Si dicho proceso no captura el aviso de su proceso hijo, ste
queda en un estado zombies. En dicho estado, el proceso no consume CPU pero
sigue ocupando recursos en la tabla de procesos (donde se guarda informacin de
cada uno de los procesos existentes en el sistema). Un proceso permanece zombi
hasta que su proceso padre captura su aviso.

PARADO

COLA DE PROCESOS
PREPARADOS EJECUTANDO ZOMBI

SUSPENDIDO

Figura 3.1: Estados de un Proceso

3.3. Identificacin de Procesos

Cada proceso se identifica mediante su PID (identificador de proceso), que es un nme-


ro entero (mayor que cero) que el sistema va asignando a cada proceso cuando ste se crea.
3.4. CREACIN DE PROCESOS: FORK() 11

El sistema operativo unix proporciona un comando que nos da informacin relativa


a cada uno de los procesos que existen en el sistema. Para obtener todos los procesos
correspondientes a un usuario usr1: ps -aux | grep usr1. Se recomienda ver el manual (man
ps).

USER: El propietario del proceso.

PID: El identificador del proceso.


% CPU: Porcentaje de CPU consumida.
% MEM: Porcentaje de memoria consumida.

SIZE: Tamao total del proceso (Kilobytes).

RSS: Kilobytes del programa en memoria. (El resto estar en disco (swapp)).

TTY: Identificador del terminal desde donde se lanz el proceso.

STAT: Estado del proceso.

START: Hora en la que empez o la que se lanz el proceso.

TIME: Tiempo de CPU consumido.

COMMAND: Nombre del proceso.

3.4. Creacin de Procesos: fork()

Los procesos pueden tener una estructura jerrquica, de manera que un proceso (pro-
ceso padre) puede crear un nuevo proceso (proceso hijo) y as sucesivamente. Para la
realizacin de aplicaciones con varios procesos, el sistema operativo unix proporciona la
llamada al sistema1 fork().

SYNOPSIS

#include <sys/types.h>
#include <unistd.h>

int fork(void);

DESCRIPCION

fork() crea un nuevo proceso exactamente igual (mismo cdigo) al proceso que invoca
la funcin. Ambos procesos continan su ejecucin tras la llamada al fork().
1
Funciones que se pueden invocar desde un programa en C, y que realizan una llamada al sistema
operativo.
12CAPTULO 3. UTILIZACIN Y GESTIN DE PROCESOS EN EL LABORATORIO

VALORES RETORNADOS
En caso de error retorna -1 y no se crea el proceso hijo. En otro caso, retorna valores
diferentes al proceso padre (el que lo invoc) y al proceso hijo (el proceso creado):
Proceso Padre: Retorna el PID del proceso hijo.
Proceso Hijo: Retorna 0.

EJEMPLO
En el ejemplo que se muestra a continuacin, se crea un proceso hijo que imprime en
pantalla el PID de su proceso padre, mientras que el proceso padre imprime en pantalla
su propio PID y el del proceso hijo que ha creado. Para ello, se utilizan las llamadas al
sistema getpid() y getppid(). El proceso padre, antes de finalizar se suspende hasta que el
hijo muere, para evitar que ste se quede zombi. Para ello, utiliza la llamada al sistema
wait(), que recibe en la variable status el estado en que el proceso hijo finaliz.

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

int main() {
int pid = 0, status = 0, pid_hijo_finalizado = 0;

if ((pid = fork()) == -1) {


printf(Error al crear proceso hijo\n);
exit(1);
}
if (pid == 0) { /* Proceso Hijo */
printf(El PID de mi proceso padre es %d\n, getppid());
exit(1);
}
else { /* Proceso Padre */
printf(Mi PID es el %d y he creado un proceso hijo cuyo pid es %d\n,
getpid(), pid);
pid_hijo_finalizado = wait(&status);
printf(\nEl proceso hijo [pid] = %d, finalizo con el estado %d\n,
pid_hijo_finalizado, status);
}
return(0);
}
3.5. EJECUCIN DE PROCESOS: EXECL() 13

3.5. Ejecucin de Procesos: execl()

Una llamada al sistema que se utiliza normalmente en combinacin con el fork() es


execl(), la cual nos permite sustituir la imagen de un proceso por otro.

SYNOPSIS

#include <unistd.h>

int execl( const char *path, const char *arg, ...);

DESCRIPCION

execl() sustituye la imagen del proceso actual por la del proceso cuyo cdigo se indica
como parmetro. Comprobar que las sentencias posteriores a un execl() no se ejecutan si
dicha funcin ha tenido xito (ya que se ha sustituido la imagen del proceso). Es decir,
despus de una llamada a execl() slo tiene sentido comprobar si se ha producido algn
error en la llamada.

PARAMETROS

path: Camino completo del programa a ejecutar.

arg: Lista de argumentos a dicho programa.

VALORES RETORNADOS

Retorna -1 si se produce algun error.

EJEMPLO

En el ejemplo que se muestra a continuacin, se crea un proceso hijo que ejecuta el


programa cuyo cdigo se encuentra en un fichero llamado esclavo. Dicho programa se
ejecuta con dos parmetros de entrada, el primero se corresponde al nombre que tomar
en la ejecucin (argv[0]), en este caso nombre; y el segundo es el parmetro -a. La lista
de argumentos termina con NULL. El proceso padre, simplemente espera a que el proceso
hijo finalice.

#include <stdio.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
14CAPTULO 3. UTILIZACIN Y GESTIN DE PROCESOS EN EL LABORATORIO

#include <stdlib.h>

int main() {
int pid = 0, status = 0;

if ((pid = fork()) == -1) {


printf(Error al crear proceso hijo\n);
exit(1);
}
if (pid == 0) { /* Proceso Hijo */
if (execl(esclavo, nombre, -a, NULL) == -1) {
printf(Error al ejecutar execl\n);
return;
}
/* Nunca llega aqui, se ha cambiado la imagen del proceso */
}
else { /* Proceso Padre */
pid_hijo_finalizado = wait(&status);
printf(\nEl proceso hijo [pid] = %d, finalizo con el estado %d\n,
pid_hijo_finalizado, status);
}
return(0);
}

A continuacin se muestra un posible cdigo del proceso esclavo, que simplemente


imprime en pantalla la lista de argumentos recibidos:

#include <stdio.h>

int main(int argc, char *argv[]) {


int i = 0;

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


return(0);
}

3.6. Compilacin

El compilador de C de GNU, denominado gcc, es un programa que llama al preproce-


sador de C, a las diversas pasadas de compilacin, y al montaje. Un programa ejemplo.c
de un slo mdulo puede compilarse y montarse as:
3.6. COMPILACIN 15

gcc ejemplo.c

Lo cual generar un ejecutable a.out. Sin embargo, normalmente se compila con la


opcin -o ejecutable que puede ir en cualquier orden:

gcc ejemplo.c -o ejemplo


gcc -o ejemplo ejemplo.c

De esta manera, el ejecutable se llamar ejemplo. Si un programa consta de varios


mdulos, pueden compilarse y montarse todos juntos. Por ejemplo, si ejemplo_bis.c
es el mdulo principal y lib_1.c y lib_2.c son mdulos auxiliares, puede compilarse y
montarse as (de nuevo, el orden es irrelevante):

gcc lib_1.c lib_2.c ejemplo_bis.c -o ejemplo_bis

Sin embargo, a veces interesa compilar por separado los distintos mdulos y luego
juntar todos los objetos en un ejecutable. El montaje se evita con la opcin -c, que genera
los ficheros objeto con extensin .o:

gcc -c ejemplo_bis.c
gcc -c lib_1.c
gcc -c lib_2.c
gcc lib_1.o lib_2.o ejemplo_bis.o -o ejemplo_bis

En el caso de que haya que montar bibliotecas ubicadas en lugares normalizados, pero
no incluidas automticamente por el montador, hay que montarlas con la opcin -l. Por
ejemplo, una compilacin y montaje utilizando la librera matemtica se realizara del
siguiente modo:

gcc -lm ejemplo.c -o ejemplo

Finalmente, conviene compilar todos los programas con la opcin -Wall para que nos
muestre toda la informacin disponible warnings de la compilacin:

gcc -Wall ejemplo.c -o ejemplo


16CAPTULO 3. UTILIZACIN Y GESTIN DE PROCESOS EN EL LABORATORIO
Captulo 4

Utilizacin de Semforos en el
Laboratorio

El sistema operativo UNIX proporciona unos mecanismos de comunicacin entre


procesos llamados ipcs. Dichos mecanismos son: memoria compartida, semforos y paso
de mensajes. Para ofrecer una interfaz de acceso a los semforos similar a la explicada en
las clases tericas, se proporciona una librera de funciones en C que encapsula el manejo
de los ipcs del sistema operativo. Dicha librera de funciones se encuentra en el fichero
/opt/ipcms/lib/libipcms.a, y su fichero de cabecera en: /opt/ipcms/include/cipcms.h.

El fichero cipcms.h contiene la declaracin de las funciones de manejo de semforos. Se


recomienda leer detenidamente la declaracin de las funciones: sem_crear(), sem_capturar(),
sem_wait(), sem_signal y sem_destruir() (la funcin sem_ver() slo se podr utilizar, en
tareas de depuracin, para mostrar el valor interno de la variable asociada al semforo).
Cada semforo se crea con una clave1 , de manera que slo los procesos que conozcan dicha
clave puedan acceder al semforo. Existe, por tanto, un proceso que crea el semforo y
que puede acceder a l a partir del identificador del semforo retornado, tal y como se
muestra a continuacin:

#include <cipcms.h>

int main() {
semaforo_t s;

s = sem_crear(1234, 1, 0); /* crea un semaforo binario de paso */


/* con la clave de acceso 1234 y retorna */
/* el descriptor del semaforo creado */
.........................
sem_wait(s);
.........................
sem_signal(s);
1
Las claves utilizadas en el laboratorio sern enteros mayores que 1000.

17
18 CAPTULO 4. UTILIZACIN DE SEMFOROS EN EL LABORATORIO

.........................
sem_destruir(s);
return(0);
}

Si algn otro proceso quiere utilizar el semforo s, deber obtener su descriptor. A


partir de ese momento, puede interaccionar con el semforo exactamente igual que el
proceso que lo cre. Una vez destruido el semforo, ningn proceso podr acceder a l.

#include <cipcms.h>

int main() {
semaforo_t s;

s = sem_capturar(1234); /* retorna el descriptor del semaforo */


/* que se creo con la clave 1234 */
.........................
sem_wait(s);
.........................
sem_signal(s);
.........................
return(0);
}

Para compilar un programa que utilice la librera libipcms.a, es necesario indicarle al


compilador la localizacin de dicha librera y la de su fichero de cabecera2 :

gcc -Wall -I /opt/ipcms/include/ - L /opt/ipcms/lib/ programa.c -lipcms -o programa

Adems, es necesario ejecutar un proceso encargado de gestionar los mecanismos de


comunicacin de bajo nivel que utiliza dicha librera. Para ello basta con ejecutar el
programa: /opt/ipcms/bin/gestoripcms. Dicho proceso debe ser ejecutado una sola vez al
iniciarse la sesin en el laboratorio. Al finalizar dicha sesin, debe finalizarse su ejecucin.
Para ello se proporciona el programa: /opt/ipcms/bin/matagestoripcms.

Si se produce algn error en la ejecucin de los programas desarrollados en el laborato-


rio, y estos se abortan anormalmente sin destruir antes los semforos creados, es necesario
abortar tambin el proceso gestoripcms y ejecutarlo de nuevo. En ese caso, y dependien-
do de cmo se abort el programa que utiliza la librera, puede ser necesario abortar la
ejecucin del proceso gestoripcms mediante el comando kill pid. En ese caso, es necesario
eliminar tambin las ipcs que estaba utilizando el proceso gestor. Para ello, existen los
comandos: ipcs (similar a ps), e ipcrm (similar a kill) (se recomienda ver el manual (man)
2
Ver la seccin 3.6.
19

de cada uno de estos comandos. A partir del comando ipcs se obtienen los identificado-
res de los ipcs activos, y con el comando ipcrm [sem id] [shm id] [msg id] se eliminan los
ipcs correspondientes a semforos (sem), memoria compartida (shm) y colas de mensajes
(msg).

Finalmente, se recomienda comprobar todos los posibles errores producidos en las lla-
madas a las funciones de manejo de semforos. En la mayora de los casos, stas retornan
un valor negativo en caso de error. (Ver fichero /opt/ipcms/include/cipcms.h).

Nota Importante: Al abandonar el laboratorio es imprescindible que se eliminen to-


dos los procesos e ipcs creados. En caso contrario, el siguiente grupo no podr ejecutar el
proceso gestoripcms, debiendo reiniciar el ordenador para poder empezar a trabajar. Para
evitar esta situacin, antes de abandonar el laboratorio se debern seguir los siguientes
pasos:

1. Ejecutar el proceso matagestoripcms.

2. Comprobar que no quedan procesos gestores en ejecucin:

>ps -aux | grep gestor

3. Si quedase algn proceso gestor, debe ser eliminado con el comando Kill pid.

4. Comprobar que no quedan ipcs activas:

>ipcs

5. Si quedase alguna ipc, debe ser eliminada con el comando ipcrm.


20 CAPTULO 4. UTILIZACIN DE SEMFOROS EN EL LABORATORIO
Captulo 5

Utilizacin de monitores en el
laboratorio

El sistema operativo unix no proporciona mecanismos de sincronizacin de alto nivel


como monitores. En el laboratorio se dispone de una implementacin software de moni-
tores en la librera libcipcms. Para crear el cdigo correspondiente a un monitor genrico
denominado monitor_ejemplo, se debern seguir los siguientes pasos (sin aadir lneas en
blanco ni comentarios):

1. Crear un fichero monitor_ejemplo.mon que contenga la declaracin del tipo de moni-


tor, las variables condition, los procedimientos ENTRY, un procedimiento de inicio
y un procedimiento de finalizacin, segn la siguiente sintaxis:

tipo: 1 (contina el proceso que seala), 2 (contina el proceso sealizado).


condicionales: nombre de las variables de tipo condition, separadas por comas, sin
ningn carcter al final de la lnea. Si la declaracin de dichas variables ocupa ms
de una lnea, no deben separarse stas con un retorno de carro, sino que se escribirn
todas seguidas.
publicos: nombre de los procedimientos de entrada al monitor. Siguen las mismas
normas que el caso anterior
inicio: nombre de la funcin que se ejecuta al iniciar el monitor.
fin: nombre de la funcin que se ejecuta al finalizar el monitor. Es necesario que
exista, aunque no haga nada.

A partir de esta cabecera, se continua como si fuera un programa C normal. En este


caso, se escribir el cdigo C de cada uno de los procedimientos del monitor:

tipo: 1
condicionales: lleno, vacio
publicos: procedimiento_1, procedimiento_3, procedimiento_4, procedim
iento_5,
inicio: inicio
fin: fin

21
22 CAPTULO 5. UTILIZACIN DE MONITORES EN EL LABORATORIO

#include <stdio.h>

void *procedimiento_1(void *)
{
}
int procedimiento_2() /* no es ENTRY */
{
}
void *procedimiento_3(void *)
{
}
void *procedimiento_4(void *)
{
}
void *procedimiento_5(void *)
{
}
void inicio()
{
}
void fin()
{
}

En la implementacin de la librera que se va a utilizar en el laboratorio, para utilizar


monitores cuyas funciones ENT RY puedan recibir parmetros, es necesario definir
dichos parmetros como punteros a void. A continuacin, se describe un ejemplo
para la resolucin de un problema productor-consumidor. Fichero buffer.mon:

tipo: 1
condicionales: vacio, lleno
publicos: producir, consumir
inicio: iniciar
fin: finalizar

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

void *producir(void *);


void *consumir(void *);
void iniciar(void);
void finalizar(void);
23

#define N 4

int buffer[N], ptr_prod, ptr_cons, num_datos;

void iniciar(void) {

ptr_prod = 0;
ptr_cons = 0;
num_datos = 0;
buffer[0]=0;
buffer[1]=0;
buffer[2]=0;
buffer[3]=0;
}

void *producir(void *dato)


{
if (num_datos == N) condm_wait(lleno);
buffer[ptr_prod] = *((int *) dato);
ptr_prod = (ptr_prod + 1) % N;
num_datos++;
condm_signal(vacio);
return(NULL);
}

void *consumir(void *nada) {


static int mi_dato = 0;

if (num_datos == 0) condm_wait(vacio);
mi_dato = buffer[ptr_cons];
ptr_cons = (ptr_cons + 1) % N;
num_datos--;
condm_signal(lleno);
return((void *) &mi_dato);
}

void finalizar(void)
{
return;
}

Para utilizar las variables de tipo condition declaradas en la cabecera existen las
funciones:

condm_wait(variable), condm_signal(variable) y condm_empty(variable).


24 CAPTULO 5. UTILIZACIN DE MONITORES EN EL LABORATORIO

2. A partir de dicho fichero, crear un fichero en C mediante el programa:

/opt/ipcms/bin/mongen.pl buffer.mon > buffer.c.

3. Compile dicho programa con la librera lipcms y la librera del sistema lpthread:

gcc -Wall -I /opt/ipcms/include/ -L /opt/ipcms/lib/ buffer.c -lipcms


-lpthread -o buffer

El ejecutable creado (buffer) no debe ejecutarse.

4. Crear un programa que cree el monitor:

#include <cipcms.h>
#include <stdio.h>

int main () {

if (mon_crear(1234, "buffer") < (monitor_t) 0)


printf("No se puedo lanzar el monitor.\n");
else printf("Monitor lanzado.\n");
return(0);
}

5. Crear un programa para finalizar su ejecucin:

#include <stdio.h>
#include <cipcms.h>

int main() {

if (mon_destruir(mon_capturar(1234)) < 0)
printf("error al destruir\n");
else printf("monitor destruido\n");
return(0);
}
25

6. Para utilizar dicho monitor desde un programa en C, declarar una variable de tipo
monitor_t, capturar su descriptor a partir de la clave con la que se cre, e invocar
a los procedimientos del monitor con la funcin.

void * monitor(monitor_t, char * nb_entry, size_t tam_entrada, size_t tam_salida, void * par_entrada)

***********
productor.c
***********
#include <stdio.h>
#include <stdlib.h>
#include <cipcms.h>

int main() {

monitor_t m;
int dato=3;

if ((m = mon_capturar(1234))<0)
{
printf("Error al capturar el monitor\n");
exit(-1);
}
printf("Producir elemento:");
fscanf(stdin,"%d", &dato);
monitor(m, "producir", sizeof(int), 0, (void *)&dato);
return(0);
}

************
consumidor.c
************
#include <stdio.h>
#include <stdlib.h>
#include <cipcms.h>

int main() {

monitor_t m;
int *dato;

if ((m = mon_capturar(1234))<0)
{
printf("Error al capturar el monitor\n");
exit(-1);
26 CAPTULO 5. UTILIZACIN DE MONITORES EN EL LABORATORIO

}
dato = (int *) (monitor(m,"consumir", 0, sizeof(int), NULL));
printf("Consumido %d\n",*dato);
return(0);
}

Estos programa se compilan con la librera ipcms, al igual que los programas que
utilizan semforos y necesitan la ejecucin previa del proceso gestoripcms.

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