13.01.2015 Views

(P10): Prácticas de Diseño Segundo Semestre Curso 2012/2013

(P10): Prácticas de Diseño Segundo Semestre Curso 2012/2013

(P10): Prácticas de Diseño Segundo Semestre Curso 2012/2013

SHOW MORE
SHOW LESS

You also want an ePaper? Increase the reach of your titles

YUMPU automatically turns print PDFs into web optimized ePapers that Google loves.

SO #<strong>2013</strong>/1<br />

Sistemas Operativos<br />

(<strong>P10</strong>): Prácticas <strong>de</strong><br />

Diseño<br />

<strong>Segundo</strong> <strong>Semestre</strong><br />

<strong>Curso</strong> <strong>2012</strong>/<strong>2013</strong><br />

Angel Rodríguez<br />

Índice<br />

1. Información general sobre las prácticas 3<br />

1.1. Valoración <strong>de</strong> cada ejercicio . . . . . . . . . . . . . 3<br />

1.2. Ejercicio presencial . . . . . . . . . . . . . . . . . . 3<br />

2. Descripción general <strong>de</strong> los ejercicios <strong>de</strong> prácticas <strong>de</strong><br />

diseño 5<br />

2.1. Ejercicios a realizar . . . . . . . . . . . . . . . . . . 5<br />

2.2. Tutorías y consultas . . . . . . . . . . . . . . . . . 5<br />

2.3. Notación . . . . . . . . . . . . . . . . . . . . . . . . 5<br />

2.4. Apertura <strong>de</strong> cuenta . . . . . . . . . . . . . . . . . . 6<br />

2.5. Código fuente <strong>de</strong> apoyo . . . . . . . . . . . . . . . 6<br />

2.6. Protección frente a copias . . . . . . . . . . . . . . 7<br />

2.7. Normas <strong>de</strong> presentación <strong>de</strong> los ejercicios . . . . . . 8<br />

2.8. Entrega <strong>de</strong> los ejercicios . . . . . . . . . . . . . . . 9<br />

2.9. Plazos <strong>de</strong> entrega . . . . . . . . . . . . . . . . . . . 10


SO #<strong>2013</strong>/1 Revisión 12.1<br />

3. Busca - Herramienta <strong>de</strong> selección <strong>de</strong> archivos 11<br />

3.1. Objetivos . . . . . . . . . . . . . . . . . . . . . . . 11<br />

3.2. Descripción . . . . . . . . . . . . . . . . . . . . . . 11<br />

3.3. Acciones <strong>de</strong>l mandato . . . . . . . . . . . . . . . . 13<br />

3.4. Páginas <strong>de</strong>l Manual a Consultar . . . . . . . . . . . 21<br />

4. Cargador - Herramienta para la carga <strong>de</strong> módulos<br />

dinámicos 23<br />

4.1. Objetivos . . . . . . . . . . . . . . . . . . . . . . . 23<br />

4.2. Descripción . . . . . . . . . . . . . . . . . . . . . . 23<br />

4.3. Acciones <strong>de</strong>l mandato . . . . . . . . . . . . . . . . 25<br />

4.4. Páginas <strong>de</strong>l manual a consultar . . . . . . . . . . . 38<br />

5. Servidor - Implementación <strong>de</strong>l servidor <strong>de</strong> un<br />

pseudo-FTP 40<br />

5.1. Objetivos . . . . . . . . . . . . . . . . . . . . . . . 40<br />

5.2. Descripción . . . . . . . . . . . . . . . . . . . . . . 40<br />

5.3. Apartados . . . . . . . . . . . . . . . . . . . . . . . 40<br />

5.4. Páginas <strong>de</strong>l manual a consultar . . . . . . . . . . . 46<br />

Registro <strong>de</strong> Revisiones 47<br />

(2)


01/02/<strong>2013</strong> SO #<strong>2013</strong>/1<br />

1. Información general sobre las prácticas<br />

La parte <strong>de</strong> prácticas <strong>de</strong> diseño <strong>de</strong> SSOO (<strong>P10</strong>) consiste en una<br />

batería <strong>de</strong> ejercicios in<strong>de</strong>pendientes que se <strong>de</strong>ben programar en<br />

C sobre UNIX. Dichos ejercicios consisten en mandatos sencillos<br />

cuyo funcionamiento se <strong>de</strong>talla en este documento.<br />

1.1. Valoración <strong>de</strong> cada ejercicio<br />

Cada ejercicio se valora <strong>de</strong> forma in<strong>de</strong>pendiente según la siguiente<br />

tabla:<br />

Cuadro 1: Tabla resumen <strong>de</strong> ejercicios a realizar<br />

Ejercicio Puntos máximos Puntos mínimos<br />

busca 35 0<br />

cargador 55 0<br />

servidor 30 0<br />

presencial 10 5<br />

Cada ejercicio dispone <strong>de</strong> un corrector asociado que <strong>de</strong>vuelve un<br />

valor con los puntos alcanzados en ese ejercicio así como la traza<br />

<strong>de</strong> la corrección. Esta traza será la referencia que se <strong>de</strong>be utilizar<br />

para <strong>de</strong>purar el código fuente.<br />

La nota total obtenida en prácticas se calcula como el total <strong>de</strong> puntos<br />

obtenidos pon<strong>de</strong>rados según lo establecido en el “Cua<strong>de</strong>rno <strong>de</strong><br />

Normas” <strong>de</strong> esta asignatura. Para superar las prácticas <strong>de</strong> diseño<br />

habrá pues que superar los puntos mínimos <strong>de</strong> cada ejercicio, y<br />

a<strong>de</strong>más la nota total obtenida <strong>de</strong>berá alcanzar el mínimo compensable<br />

indicado en el “Cua<strong>de</strong>rno <strong>de</strong> Normas” <strong>de</strong> esta asignatura.<br />

1.2. Ejercicio presencial<br />

Una vez finalizados los plazos <strong>de</strong> entrega <strong>de</strong> los diferentes ejercicios<br />

prácticos, se proce<strong>de</strong>rá a la realización <strong>de</strong> un ejercicio más, <strong>de</strong><br />

(3)


SO #<strong>2013</strong>/1 Revisión 12.1<br />

carácter presencial, en el cual se exigirá sacar la nota mínima recogida<br />

en la tabla anterior. Sólo se podrán presentar a este ejercicio<br />

aquellos alumnos que hayan alcanzado con los <strong>de</strong>más ejercicios nota<br />

suficiente para po<strong>de</strong>r aspirar a superar el mínimo compensable.<br />

El profesorado <strong>de</strong> la asignatura podrá <strong>de</strong>cidir eximir <strong>de</strong> la realización<br />

<strong>de</strong> la prueba a aquellos alumnos <strong>de</strong> los que tenga constancia<br />

que durante el curso han realizado un buen aprovechamiento <strong>de</strong><br />

los ejercicios prácticos <strong>de</strong> diseño.<br />

(4)


01/02/<strong>2013</strong> SO #<strong>2013</strong>/1<br />

2. Descripción general <strong>de</strong> los ejercicios <strong>de</strong> prácticas <strong>de</strong><br />

diseño<br />

2.1. Ejercicios a realizar<br />

La práctica <strong>de</strong> diseño consiste en la siguiente batería <strong>de</strong> ejercicios:<br />

➀ busca: Utilidad para buscar contenidos en el árbol <strong>de</strong> directorios.<br />

➁ cargador: Utilidad para gestionar la carga dinámica <strong>de</strong> un<br />

plugin y controlar la ejecución <strong>de</strong> instancias <strong>de</strong>l mismo.<br />

➂ servidor: Implementación <strong>de</strong> un servidor reducido <strong>de</strong> un protocolo<br />

pseudo-FTP en base a sockets.<br />

➃ ejercicio presencial: Este ejercicio se realizará <strong>de</strong> forma<br />

presencial.<br />

2.2. Tutorías y consultas<br />

Los profesores encargados <strong>de</strong> esta práctica y su dirección <strong>de</strong> correo<br />

son:<br />

Angel Rodríguez <br />

2.3. Notación<br />

A lo largo <strong>de</strong>l enunciado <strong>de</strong> los diferentes ejercicios se usará la<br />

siguiente notación:<br />

texto Secuencia <strong>de</strong> caracteres proporcionada por el usuario.<br />

texto Salida generada por el programa por su salida estándar.<br />

texto Salida generada por el programa por su error estándar.<br />

✿✿✿✿✿✿✿<br />

(5)


SO #<strong>2013</strong>/1 Revisión 12.1<br />

Importante: Sea muy cuidadoso en lo correspondiente<br />

a entradas y, sobre todo, salidas <strong>de</strong>l<br />

programa. La corrección automática buscará una<br />

salida <strong>de</strong>terminada y concreta en cada prueba <strong>de</strong><br />

ejecución <strong>de</strong> los programas.<br />

2.4. Apertura <strong>de</strong> cuenta<br />

Para la entrega <strong>de</strong> las prácticas, cada alumno <strong>de</strong>be abrir cuenta<br />

en la máquina UNIX <strong>de</strong>nominada triqui(1, 2, 3 ó 4), para lo<br />

cual, el interesado <strong>de</strong>berá acudir al Centro <strong>de</strong> Cálculo con un justificante<br />

<strong>de</strong> estar matriculado en la asignatura.<br />

Es obligatoria la entrega <strong>de</strong> las prácticas <strong>de</strong>s<strong>de</strong> la máquina asignada<br />

por el Centro <strong>de</strong> Cálculo. Sin embargo, para la realización <strong>de</strong><br />

las mismas es posible utilizar otras máquinas o realizar las mismas<br />

<strong>de</strong>s<strong>de</strong> casa. La entrega obligatoriamente se <strong>de</strong>be hacer <strong>de</strong>s<strong>de</strong><br />

triqui(1, 2, 3 ó 4).<br />

Importante: Los horarios concretos <strong>de</strong> acceso a<br />

las máquinas serán gestionados por el Centro <strong>de</strong><br />

Cálculo<br />

2.5. Código fuente <strong>de</strong> apoyo<br />

Normalmente, para la realización <strong>de</strong> cada ejercicio práctico,<br />

no se partirá <strong>de</strong> cero, sino <strong>de</strong> un <strong>de</strong>terminado material <strong>de</strong><br />

apoyo. Este material podrá obtenerse <strong>de</strong>s<strong>de</strong> la página web<br />

<strong>de</strong> la asignatura http://laurel.datsi.fi.upm.es/docencia/<br />

asignaturas/so6 y consistirá en un paquete con el nombre <strong>de</strong>l<br />

ejercicio en cuestión, i<strong>de</strong>ntificación <strong>de</strong>l año en curso y extensión<br />

<strong>de</strong> archivo comprimido (P. ej. .<strong>2013</strong>.tar.gz).<br />

(6)


01/02/<strong>2013</strong> SO #<strong>2013</strong>/1<br />

Una vez en su cuenta y <strong>de</strong>s<strong>de</strong> su home, <strong>de</strong>scomprima y <strong>de</strong>sempaquete<br />

estos ficheros.<br />

sh> gunzip -c .<strong>2013</strong>.tar.gz | tar xvf -<br />

sh> rm .<strong>2013</strong>.tar.gz<br />

2.6. Protección frente a copias<br />

El objetivo primordial <strong>de</strong> las prácticas es conseguir que el alumno,<br />

con su realización, obtenga una experiencia que le será muy útil.<br />

Persiguiendo esta meta fundamental, prestaremos especial interés<br />

en <strong>de</strong>tectar los intentos <strong>de</strong> copia total o parcial <strong>de</strong> prácticas.<br />

Para evitar problemas <strong>de</strong> confi<strong>de</strong>ncialidad y posibles copias, <strong>de</strong>berá<br />

tenerse especial cuidado en proteger la propia cuenta <strong>de</strong> accesos<br />

no <strong>de</strong>seados. Para ello se <strong>de</strong>ben seguir las siguientes pautas:<br />

✍ En cuanto le abran cuenta, proceda a entrar en la misma<br />

para protegerla.<br />

✍ Ponga inmediatamente una palabra clave <strong>de</strong> acceso a su<br />

cuenta usando el mandato passwd. Pasado un tiempo <strong>de</strong>s<strong>de</strong><br />

su apertura, se proce<strong>de</strong>rá a cerrar las cuentas sin palabra<br />

clave. Escoja una palabra clave que tenga caracteres especiales<br />

para que la protección sea más efectiva. No le diga su<br />

palabra clave a nadie.<br />

✍ Proteja el directorio home <strong>de</strong> su cuenta contra todo tipo <strong>de</strong><br />

acceso <strong>de</strong> cualquier otro usuario usando el mandato chmod<br />

0700 $HOME.<br />

✍ Cambie la mascara <strong>de</strong> creación <strong>de</strong> ficheros para proteger<br />

cualquier fichero que cree en su cuenta. Para ello añada al<br />

final <strong>de</strong>l fichero .bashrc el mandato umask 077.<br />

✍ No saque listados si no pue<strong>de</strong> esperar a recogerlos.<br />

(7)


SO #<strong>2013</strong>/1 Revisión 12.1<br />

✍ Si sospecha que le han robado los fuentes con la solución <strong>de</strong><br />

alguna práctica, comuníquelo al profesor <strong>de</strong> la misma utilizando<br />

correo electrónico y, MUY IMPORTANTE, adjunte<br />

la versión perdida <strong>de</strong>l documento.<br />

login: MiCuenta<br />

Password: ****<br />

sh> passwd<br />

New password: MiComplejaPalabraClave<br />

Retype new password: MiComplejaPalabraClave<br />

sh> chmod 0700 $HOME<br />

sh> echo umask 0077 >> $HOME/.cshrc<br />

2.7. Normas <strong>de</strong> presentación <strong>de</strong> los ejercicios<br />

❒ El código fuente <strong>de</strong> las prácticas, esto es, el <strong>de</strong> los programas<br />

que exija cada enunciado, <strong>de</strong>be residir, en su cuenta<br />

en la máquina <strong>de</strong> prácticas, en un directorio que i<strong>de</strong>ntifica<br />

la asignatura, el ejercicio y el curso al que pertenece:<br />

DATSI/so6/ (tres niveles <strong>de</strong>s<strong>de</strong> el directorio<br />

HOME <strong>de</strong> la cuenta). El nombre <strong>de</strong>l directorio se obtiene<br />

directamente al <strong>de</strong>sempaquetar el software <strong>de</strong> apoyo en el<br />

directorio HOME <strong>de</strong>l alumno.<br />

❒ No es necesario entregar ningún documento en papel para<br />

entregar cada ejercicio. Toda la entrega se realiza <strong>de</strong> forma<br />

telemática, ejecutando un programa en la misma máquina<br />

en la que se hace el <strong>de</strong>sarrollo.<br />

❒ Antes <strong>de</strong> realizar la entrega ejecute make entrega para eliminar<br />

tanto ficheros ejecutables como ficheros .o, <strong>de</strong>jando<br />

únicamente las fuentes comprimidas en un fichero <strong>de</strong>nominado<br />

.<strong>2013</strong>.entrega.tar.gz.<br />

❒ El mandato a ejecutar para entregar las prácticas está en<br />

el directorio /usr/local/bin/ y se llama entrega.so6.<br />

(8)


01/02/<strong>2013</strong> SO #<strong>2013</strong>/1<br />

Asegúrense <strong>de</strong> que la entrega se realiza correctamente. En caso<br />

<strong>de</strong> error, la utilidad <strong>de</strong> entrega lo indicaría. Este mandato<br />

realiza la recolección <strong>de</strong> los ficheros indicados en el apartado<br />

Documentación a Entregar <strong>de</strong> cada ejercicio. En concreto<br />

siempre se recogerán los siguientes:<br />

➀ autores.txt Fichero ASCII con los datos <strong>de</strong>l autor <strong>de</strong>l<br />

ejercicio.<br />

Cada línea presentará cinco tiras <strong>de</strong> caracteres separadas<br />

por blancos o tabuladores. DNI o número <strong>de</strong> Pasaporte,<br />

primer apellido, segundo apellido, nombre y<br />

número <strong>de</strong> matrícula. Separe las partes <strong>de</strong> los nombres<br />

o apellidos compuestos con el caracter subrayado ( ),<br />

no utilice blancos ni tabuladores.<br />

Ejemplo:<br />

P12456212F Garcia De La Torre Maria Dolores<br />

910347<br />

➁ bitacora.txt Fichero ASCII con comentarios reseñables<br />

sobre la realización <strong>de</strong>l ejercicio, que <strong>de</strong>berá <strong>de</strong>sarrollar<br />

los siguientes puntos: autor, problemas que se han<br />

planteado, comentarios personales, crítica constructiva,<br />

propuesta <strong>de</strong> mejoras, estimación <strong>de</strong>l tiempo <strong>de</strong>dicado<br />

en la realización, etc.<br />

2.8. Entrega <strong>de</strong> los ejercicios<br />

El mandato a ejecutar para entregar cada ejercicio será:<br />

sh> make entrega<br />

sh> entrega.so6 .<strong>2013</strong><br />

Este mandato recogerá los siguientes ficheros:<br />

autores.txt<br />

Descrito en el apartado 2.7 Normas <strong>de</strong> presentación.<br />

(9)


SO #<strong>2013</strong>/1 Revisión 12.1<br />

bitacora.txt<br />

Descrito en el apartado 2.7 Normas <strong>de</strong> presentación.<br />

.<strong>2013</strong>.entrega.tar.gz<br />

Fichero comprimido <strong>de</strong> los códigos fuente, correspondiente a<br />

la batería <strong>de</strong> ejercicios (creado al ejecutarse make entrega).<br />

2.9. Plazos <strong>de</strong> entrega<br />

Cada ejercicio <strong>de</strong>berá entregarse <strong>de</strong> forma in<strong>de</strong>pendiente antes <strong>de</strong><br />

la fecha tope <strong>de</strong> entrega indicada en la página web <strong>de</strong> la asignatura.<br />

Dicha fecha será inamovible. Los puntos correspondientes a un<br />

ejercicio que no se hayan conseguido antes <strong>de</strong> la fecha tope <strong>de</strong><br />

entrega se habrán perdido.<br />

Junto con las fechas tope <strong>de</strong> entrega, se publicarán unas fechas<br />

adicionales que reconocerán el esfuerzo realizado al entregar los<br />

ejercicios anticipadamente y alcanzar al menos el 90 % <strong>de</strong> la nota<br />

máxima correspondiente al ejercicio. Aquellos alumnos que cumplan<br />

este requisito <strong>de</strong> entrega anticipada en todos los ejercicios<br />

obligatorios, serán eximidos <strong>de</strong> cumplir el requisito <strong>de</strong> asistencia<br />

obligatoria al horario reservado para las prácticas <strong>de</strong> diseño.<br />

Importante: No se permitirá entregar un ejercicio<br />

fuera <strong>de</strong> su correspondiente plazo.<br />

(10)


01/02/<strong>2013</strong> SO #<strong>2013</strong>/1<br />

3. Busca - Herramienta <strong>de</strong> selección <strong>de</strong> archivos<br />

3.1. Objetivos<br />

El alumno <strong>de</strong>be <strong>de</strong>sarrollar una aplicación capaz <strong>de</strong> realizar la<br />

búsqueda <strong>de</strong> ficheros <strong>de</strong>ntro <strong>de</strong>l árbol <strong>de</strong> directorios <strong>de</strong> acuerdo<br />

a unos criterios especificados como argumentos en la ejecución<br />

<strong>de</strong> la aplicación. Los resultados <strong>de</strong> la búsqueda se mostrarán por<br />

pantalla (en el caso más sencillo) o se convertirán en argumentos<br />

para la ejecución <strong>de</strong> otros mandatos.<br />

La aplicación, <strong>de</strong>nominada busca, se ejecutará con <strong>de</strong>terminados<br />

argumentos, y retornará los resultados <strong>de</strong> las operaciones solicitadas<br />

o mensajes <strong>de</strong> error en caso <strong>de</strong> producirse algún problema.<br />

3.2. Descripción<br />

3.2.1. Uso <strong>de</strong> la aplicación: El programa “busca” se invocará<br />

<strong>de</strong>s<strong>de</strong> el intérprete <strong>de</strong> mandatos (shell) indicándole una serie<br />

<strong>de</strong> argumentos que parametrizan su funcionamiento. El objeto general<br />

<strong>de</strong>l programa es realizar una búsqueda <strong>de</strong> los archivos <strong>de</strong>s<strong>de</strong><br />

el directorio que se indica como primer argumento en a<strong>de</strong>lante.<br />

Los archivos que se seleccionarán serán aquellos que cumplan con<br />

una <strong>de</strong>terminada condición indicada también como argumento <strong>de</strong>l<br />

programa. Esta parte <strong>de</strong> los argumentos se <strong>de</strong>nominará en a<strong>de</strong>lante<br />

criterio <strong>de</strong> selección.<br />

Una vez seleccionados los archivos que cumplen el criterio <strong>de</strong> selección,<br />

el programa “busca” pue<strong>de</strong>, o bien presentar la lista <strong>de</strong><br />

los que cumplen la condición <strong>de</strong> selección, o ejecutar un programa<br />

que reciba dicha lista <strong>de</strong> archivos. Otra alternativa es la ejecución<br />

<strong>de</strong> un programa por cada archivo seleccionado (que reciba<br />

dicho archivo como argumento). Esta parte <strong>de</strong> los argumentos se<br />

<strong>de</strong>nominará <strong>de</strong> aquí en a<strong>de</strong>lante acción a aplicar.<br />

La búsqueda <strong>de</strong> archivos se realizará solo en el directorio indicado<br />

como argumento, no en subdirectorios que estén <strong>de</strong>ntro <strong>de</strong> él. Es<br />

<strong>de</strong>cir, no se realizará búsqueda recursiva.<br />

(11)


SO #<strong>2013</strong>/1 Revisión 12.1<br />

Si por cualquier motivo, alguna operación no se pue<strong>de</strong> realizar (por<br />

ejemplo, entrar en un directorio), el programa sacará por el error<br />

estándar un mensaje con el formato: "%s:␣Error(%d),␣%s\n"<br />

don<strong>de</strong>:<br />

❒ ␣ es un espacio en blanco.<br />

❒ El primer campo ( %s) es el nombre completo <strong>de</strong>l ejecutable<br />

(argv[0]).<br />

❒ El segundo campo ( %d) es el código <strong>de</strong> error (ver sección<br />

3.3.5 y los diferentes tipos <strong>de</strong> errores correspondientes a las<br />

distintas opciones seleccionables).<br />

❒ El último campo ( %s) es el texto <strong>de</strong>l mensaje <strong>de</strong> error generado.<br />

Alguna <strong>de</strong> las operaciones pue<strong>de</strong>n generar errores (por ejemplo,<br />

no po<strong>de</strong>r leer un archivo). En ese caso el programa generará un<br />

error, pero continuará ejecutando el resto <strong>de</strong> operaciones que pueda<br />

completar (por ejemplo, seguir leyendo el contenido <strong>de</strong> otros<br />

archivos.). Los errores no abortan la ejecución <strong>de</strong>l programa. El<br />

programa <strong>de</strong>volverá por medio <strong>de</strong> la llamada exit(int) el valor<br />

<strong>de</strong> error <strong>de</strong> la última operación que dio error ó 0 si ninguna operación<br />

dio problemas. Los códigos <strong>de</strong> error que se pue<strong>de</strong>n dar en<br />

cada operación vienen indicados en los siguientes apartados.<br />

Ejemplo <strong>de</strong> salida <strong>de</strong>l programa:<br />

[usuario@maquina ~] busca . -n .doc -print<br />

./fichero.doc<br />

./texto.doc<br />

./tecto.doc.bak<br />

Ejemplo <strong>de</strong> caso <strong>de</strong> error:<br />

(12)


01/02/<strong>2013</strong> SO #<strong>2013</strong>/1<br />

[usuario@maquina ~] busca /home/frosal -n .doc<br />

-print<br />

busca: Error(2), No se pue<strong>de</strong> leer el directorio<br />

✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿<br />

3.2.2. Sintaxis <strong>de</strong> la ĺınea <strong>de</strong> mandato <strong>de</strong>l programa: La estructura<br />

general <strong>de</strong> una llamada a busca se encuentra recogida en<br />

la ✞ siguiente estructura:<br />

☎<br />

busca directorio inicial criterio <strong>de</strong> seleccion acción a aplicar<br />

✝<br />

✆<br />

Todos los argumentos son obligatorios.<br />

El argumento directorio inicial indica la ruta, absoluta o relativa<br />

<strong>de</strong>s<strong>de</strong> la cual se realizará la búsqueda.<br />

El criterio <strong>de</strong> seleccion representa cuáles serán los archivos seleccionados.<br />

En las siguientes secciones se irán indicando las diferentes<br />

opciones <strong>de</strong> selección que se <strong>de</strong>berán implementar.<br />

La acción a aplicar representa qué es lo que se hace con los archivos<br />

seleccionados. Las diferentes acciones a implementar también<br />

se discutirán en las siguientes secciones.<br />

3.3. Acciones <strong>de</strong>l mandato<br />

El mandato busca <strong>de</strong>berá realizar las siguientes acciones:<br />

➀ Selección basada en tipo <strong>de</strong> archivo<br />

➁ Selección basada en nombre <strong>de</strong> archivo<br />

➂ Selección basada en permisos<br />

➃ Acción <strong>de</strong> imprimir archivos seleccionados<br />

➄ Gestión <strong>de</strong> errores básicos<br />

➅ Selección basada en el contenido <strong>de</strong>l archivo (lectura <strong>de</strong>l mismo).<br />

(13)


SO #<strong>2013</strong>/1 Revisión 12.1<br />

➆ Selección basada en el contenido <strong>de</strong>l archivo (proyección en<br />

memoria).<br />

➇ Acción <strong>de</strong> procesar la lista <strong>de</strong> archivos por medio <strong>de</strong> otro<br />

programa.<br />

➈ Acción <strong>de</strong> ejecutar un programa por cada archivo.<br />

Se recuerda que en el filtro <strong>de</strong> selección <strong>de</strong> archivos, el propio<br />

proceso <strong>de</strong> búsqueda sólo se aplica al directorio indicado como<br />

primer argumento, no es una búsqueda recursiva.<br />

3.3.1. Selección por tipo <strong>de</strong> archivo: Consiste en seleccionar<br />

aquellas entradas <strong>de</strong>l directorio a analizar que cumplan la condición<br />

<strong>de</strong> ser fichero (f) o directorio (d).<br />

Este ✞ criterio <strong>de</strong> selección se <strong>de</strong>clara como: ☎<br />

busca directorio inicial -t [f|d] acción a aplicar<br />

✝<br />

✆<br />

La combinación -t f seleccionará los ficheros y la opción -t d<br />

seleccionará los directorios.<br />

ERROR<br />

Código Mensaje<br />

1 Opcion no valida<br />

Este error se produce cuando el tipo <strong>de</strong> entrada<br />

que se pi<strong>de</strong> seleccionar no es ni f ni d. Este<br />

error se aplicará también a otros parámetros no<br />

válidos.<br />

3.3.2. Selección por nombre <strong>de</strong> archivo: Consiste en seleccionar<br />

aquellas entradas <strong>de</strong>l directorio a analizar que cumplan la<br />

condición <strong>de</strong> contener en el nombre la subca<strong>de</strong>na pasada como<br />

argumento. Si dicha ca<strong>de</strong>na aparece <strong>de</strong>ntro <strong>de</strong>l nombre, el fichero<br />

pasará el criterio <strong>de</strong> selección.<br />

(14)


01/02/<strong>2013</strong> SO #<strong>2013</strong>/1<br />

Este ✞ criterio <strong>de</strong> selección se <strong>de</strong>clara como:<br />

☎<br />

busca directorio inicial -n ca<strong>de</strong>na acción a aplicar<br />

✝<br />

✆<br />

La llamada con -n pepe seleccionará todos los ficheros y directorios<br />

que contengan pepe en su nombre.<br />

3.3.3. Selección por permisos <strong>de</strong> archivo: Consiste en seleccionar<br />

aquellas entradas <strong>de</strong>l directorio a analizar que cumplan la<br />

condición <strong>de</strong> ser ejecutables (x) o <strong>de</strong> tener permisos <strong>de</strong> lectura (r)<br />

o <strong>de</strong> escritura (w).<br />

Este ✞ criterio <strong>de</strong> selección se <strong>de</strong>clara como:<br />

☎<br />

busca directorio inicial -p [x|r|w] acción a aplicar<br />

✝<br />

✆<br />

Los archivos seleccionados <strong>de</strong>berán disponer <strong>de</strong>l permiso indicado<br />

para el usuario. Es <strong>de</strong>cir, que se <strong>de</strong>be verificar el primer bloque <strong>de</strong><br />

permisos, si es el mismo usuario, el segundo bloque si es un usuario<br />

<strong>de</strong>l mismo grupo, o en caso contrario el último bloque. Para ello<br />

se <strong>de</strong>berá gestionar correctamente la i<strong>de</strong>ntidad <strong>de</strong>l usuario.<br />

✍ NOTA: La i<strong>de</strong>ntidad <strong>de</strong> grupo que se cotejará será la <strong>de</strong>l grupo<br />

primario <strong>de</strong>l usuario. Es <strong>de</strong>cir la asignada como i<strong>de</strong>ntificador <strong>de</strong><br />

grupo <strong>de</strong>l proceso.<br />

✍ NOTA: Es necesario tener en cuenta la i<strong>de</strong>ntidad efectiva <strong>de</strong>l<br />

proceso, es <strong>de</strong>cir el EUID y el EGID (no la real, UID y GID)<br />

ERROR<br />

Código Mensaje<br />

1 Opcion no valida<br />

Este error también se produce cuando el permiso<br />

no es ni x, ni r, ni w.<br />

3.3.4. Impresión <strong>de</strong> archivos: Es la acción a aplicar más básica.<br />

Consiste en mostrar por la salida estándar la lista <strong>de</strong> archivos que<br />

cumplan el criterio <strong>de</strong> selección.<br />

Esta ✞ acción se <strong>de</strong>clara como:<br />

☎<br />

busca dir inicial crit <strong>de</strong> seleccion -print<br />

✝<br />

✆<br />

(15)


SO #<strong>2013</strong>/1 Revisión 12.1<br />

La lista <strong>de</strong> archivos generada mantendrá la ruta incluyendo el<br />

directorio indicado como argumento. Por ejemplo si se busca <strong>de</strong>s<strong>de</strong><br />

el directorio /tmp las salidas serán <strong>de</strong>l tipo /tmp/pepe.c. Si<br />

por contra, se busca en el directorio actual (.), las salidas serán<br />

./pepe.c.<br />

✍ NOTA: La salida <strong>de</strong> los resultados se realizará en el mismo<br />

or<strong>de</strong>n en el que aparezcan en el directorio consultado. No será necesario<br />

or<strong>de</strong>nar los archivos bajo ningún criterio. Se mostrarán<br />

según se obtengan <strong>de</strong> las funciones POSIX que recorren el directorio<br />

(opendir, readdir, etc.).<br />

✍ NOTA: Las entradas <strong>de</strong> directorio que comiencen por un punto<br />

(.) se ignorarán.<br />

3.3.5. Gestión <strong>de</strong> errores básicos: Debe implementarse el control<br />

<strong>de</strong> los siguientes tipos <strong>de</strong> errores básicos:<br />

ERROR<br />

Código Mensaje<br />

1 Opcion no valida<br />

Este error, que ya hemos visto antes, se producirá<br />

siempre que los argumentos <strong>de</strong> un criterio<br />

<strong>de</strong> selección o <strong>de</strong> una acción a aplicar sean incorrectos.<br />

ERROR<br />

Código Mensaje<br />

2 No se pue<strong>de</strong> leer el directorio<br />

Este error se producirá cuando los permisos <strong>de</strong>l<br />

directorio sobre el que se realiza la búsqueda no<br />

permitan efectuar las operaciones <strong>de</strong> recorrido<br />

<strong>de</strong> sus entradas.<br />

3.3.6. Selección por contenido <strong>de</strong> archivo (lectura): En este<br />

caso se seleccionarán los archivos que contengan una <strong>de</strong>terminada<br />

(16)


01/02/<strong>2013</strong> SO #<strong>2013</strong>/1<br />

subca<strong>de</strong>na pasada como argumento adicional <strong>de</strong> esta selección.<br />

Este ✞ criterio <strong>de</strong> selección se <strong>de</strong>clara como:<br />

☎<br />

busca directorio inicial -c ca<strong>de</strong>na acción a aplicar<br />

✝<br />

✆<br />

Los archivos seleccionados serán aquellos en cuyo interior se localice<br />

la ca<strong>de</strong>na indicada. La búsqueda <strong>de</strong> esta ca<strong>de</strong>na se realizará<br />

abriendo el fichero, y leyendo <strong>de</strong>l mismo su contenido. Dentro<br />

<strong>de</strong> este contenido se buscará la ca<strong>de</strong>na solicitada.<br />

✍ NOTA: Los directorios no se consultarán. Un directorio nunca<br />

se podrá seleccionar por medio <strong>de</strong> este criterio <strong>de</strong> selección.<br />

ERROR<br />

Código Mensaje<br />

3 No se pue<strong>de</strong> leer el archivo<br />

Este error se generará por cada uno <strong>de</strong> los archivos<br />

sobre los que no se tenga permiso <strong>de</strong> lectura<br />

3.3.7. Selección por contenido <strong>de</strong> archivo (proyección): En<br />

este caso, al igual que en el anterior, se seleccionarán los archivos<br />

que contengan la ca<strong>de</strong>na indicada como argumento adicional <strong>de</strong><br />

esta selección.<br />

Este ✞ criterio <strong>de</strong> selección se <strong>de</strong>clara como:<br />

☎<br />

busca directorio inicial -C ca<strong>de</strong>na acción a aplicar<br />

✝<br />

✆<br />

Los archivos seleccionados serán aquellos en cuyo interior se localice<br />

la ca<strong>de</strong>na indicada. La búsqueda <strong>de</strong> esta ca<strong>de</strong>na se realizará,<br />

en este caso, proyectando el archivo en memoria.<br />

✍ NOTA: Los directorios no se consultarán. Un directorio nunca<br />

se podrá seleccionar por medio <strong>de</strong> este criterio <strong>de</strong> selección.<br />

ERROR<br />

Código Mensaje<br />

3 No se pue<strong>de</strong> leer el archivo<br />

Este error se generará por cada uno <strong>de</strong> los archivos<br />

sobre los que no se tenga permiso <strong>de</strong> lectura<br />

(17)


SO #<strong>2013</strong>/1 Revisión 12.1<br />

3.3.8. Procesar lista <strong>de</strong> archivos: En este caso, el resultado <strong>de</strong>l<br />

proceso <strong>de</strong> selección, la lista <strong>de</strong> archivos seleccionados, se pasa<br />

por medio <strong>de</strong> un pipe (tubería) a otro programa. Este programa<br />

se facilita como argumento <strong>de</strong> la acción a aplicar junto con los<br />

argumentos que a su vez necesite.<br />

Esta ✞ acción se <strong>de</strong>clara como:<br />

☎<br />

busca dir inicial crit <strong>de</strong> selección -pipe mandato [argumentos ...]<br />

✝<br />

✆<br />

La lista <strong>de</strong> archivos generada, que en el caso <strong>de</strong> la acción -print<br />

se sacaba por la salida estándar, se pasa al mandato que aparece<br />

a continuación. Dicho mandato se ejecutará con los argumentos<br />

indicados.<br />

La acción a realizar <strong>de</strong>be ser análoga a sacar los datos por la salida<br />

estándar y redirigir ésta por un pipe a la entrada estándar <strong>de</strong> otro<br />

proceso.<br />

Ejemplo <strong>de</strong> salida <strong>de</strong>l programa con un pipe:<br />

[usuario@maquina ~] busca . -n .doc -print | sort<br />

./documento.doc<br />

./hola.doc<br />

./practica.doc<br />

Ejemplo <strong>de</strong> salida con pipe integrado:<br />

[usuario@maquina ~] busca . -n .doc -pipe sort<br />

./documento.doc<br />

./hola.doc<br />

./practica.doc<br />

ERROR<br />

Código Mensaje<br />

4 No se pue<strong>de</strong> ejecutar el mandato<br />

Este error se dará si el mandato que se indica<br />

no se pue<strong>de</strong> ejecutar correctamente<br />

(18)


01/02/<strong>2013</strong> SO #<strong>2013</strong>/1<br />

✍ NOTA: En este caso el valor <strong>de</strong> retorno (el <strong>de</strong> la llamada<br />

exit(int)) será el recogido <strong>de</strong>l mandato que se ha ejecutado como<br />

receptor <strong>de</strong> la lista <strong>de</strong> archivos.<br />

3.3.9. Ejecución secuencial <strong>de</strong> un programa por archivo: Esta<br />

acción consiste en lanzar un proceso por cada uno <strong>de</strong> los archivos<br />

que cumplan el criterio <strong>de</strong> selección. La ejecución <strong>de</strong> estos procesos<br />

será secuencial, es <strong>de</strong>cir, que se ejecutarán uno a uno, esperando<br />

a la finalización <strong>de</strong> cada uno para lanzar el siguiente.<br />

Esta ✞ acción se <strong>de</strong>clara como:<br />

☎<br />

busca dir inicial crit <strong>de</strong> seleccion -exec mandato [argumentos ...]<br />

✝<br />

✆<br />

Los procesos hijo que se arrancarán por cada fichero seleccionado<br />

serán ✞ <strong>de</strong> la forma:<br />

☎<br />

mandato [argumentos ...] fichero seleccionado<br />

✝<br />

✆<br />

Siendo mandato y argumentos los que aparecen tras la directiva<br />

-exec en la llamada al mandato busca.<br />

Ejemplo <strong>de</strong> ejecución <strong>de</strong> un progrma por archivo:<br />

[usuario@maquina ~] busca . -C data -exec wc -l<br />

2 23 100 ./datost<br />

138 230 2900 ./fichero gran<strong>de</strong><br />

En este ejemplo se ve cómo se ejecuta el mandato wc una vez por<br />

cada fichero que contiene la ca<strong>de</strong>na “data” en su interior. Este<br />

mandato cuenta la líneas, palabras y caracteres que aparecen en<br />

el fichero.<br />

Timeout: Para la ejecución <strong>de</strong> programas por cada archivo, el<br />

programa busca <strong>de</strong>be establecer un control que prevenga ejecuciones<br />

excesivamente largas por parte <strong>de</strong> los procesos lanzados. Para<br />

ello, busca leerá una variable <strong>de</strong> entorno, <strong>de</strong>nominada BUSCATIME,<br />

(19)


SO #<strong>2013</strong>/1 Revisión 12.1<br />

que indicará el número <strong>de</strong> segundos, como máximo, que esperará<br />

busca a que todos los mandatos hayan concluido. Este<br />

timeout comenzará a contar antes <strong>de</strong> arrancar el primer mandato.<br />

En el momento en que se cumpla, no se arrancarán nuevos<br />

procesos (<strong>de</strong> quedar pendiente alguno), y se abortará la ejecución<br />

<strong>de</strong>l que pueda estar en curso. Para abortar el posible proceso en<br />

ejecución se le mandará una señal SIGKILL (ver kill(2)). Si la<br />

variable <strong>de</strong> entorno BUSCATIME no existiera, se <strong>de</strong>berá tomar 0<br />

como valor por <strong>de</strong>fecto.<br />

ERROR<br />

Código Mensaje<br />

5 Timeout<br />

Este error se generará si el timeout indicado por<br />

la variable BUSCATIME se cumple antes <strong>de</strong> haber<br />

finalizado la ejecución <strong>de</strong> todos los procesos.<br />

✍ NOTA: En este caso el valor <strong>de</strong> retorno (el <strong>de</strong> la llamada<br />

exit(int)) será el recogido <strong>de</strong>l mandato que se ha ejecutado como<br />

receptor <strong>de</strong> la lista <strong>de</strong> archivos (en el caso <strong>de</strong> que la ejecución no<br />

haga saltar el timeout, si dicha temporización vence se dará el<br />

error antes citado (Error 5))<br />

Adicionalmente se podrá dar el caso <strong>de</strong> no po<strong>de</strong>r ejecutar uno o<br />

varios errores <strong>de</strong> tipo 4:<br />

ERROR<br />

Código Mensaje<br />

4 No se pue<strong>de</strong> ejecutar el mandato<br />

Este error se dará si el mandato que se indica no<br />

se pue<strong>de</strong> ejecutar correctamente. Aparecerá por<br />

la salida <strong>de</strong> error estándar una línea por cada<br />

mandato que no se pueda ejecutar.<br />

(20)


01/02/<strong>2013</strong> SO #<strong>2013</strong>/1<br />

3.4. Páginas <strong>de</strong>l Manual a Consultar<br />

A título <strong>de</strong> ayuda se recomienda la consulta <strong>de</strong> los siguientes servicios<br />

o funciones en las páginas <strong>de</strong>l manual. Dichas páginas se<br />

pue<strong>de</strong>n consultar vía el mandato man):<br />

❒ stat(2)<br />

❒ opendir(3)<br />

❒ readdir(3)<br />

❒ closedir(3)<br />

❒ Alternativa a las tres anteriores: scandir(3)<br />

❒ getuid(2)<br />

❒ geteuid(2)<br />

❒ getgid(2)<br />

❒ getegid(2)<br />

❒ open(2)<br />

❒ read(2)<br />

❒ mmap(2)<br />

❒ munmap(2)<br />

❒ close(2)<br />

❒ memmem(3)<br />

❒ fork(2)<br />

❒ execvp(3)<br />

❒ dup(2)<br />

(21)


SO #<strong>2013</strong>/1 Revisión 12.1<br />

❒ pipe(2)<br />

❒ wait(2)<br />

❒ kill(2)<br />

❒ sigaction(2) o signal(2)<br />

❒ getenv(3)<br />

❒ alarm(2)<br />

❒ exit(2)<br />

(22)


01/02/<strong>2013</strong> SO #<strong>2013</strong>/1<br />

4. Cargador - Herramienta para la carga <strong>de</strong> módulos<br />

dinámicos<br />

4.1. Objetivos<br />

El alumno <strong>de</strong>be <strong>de</strong>sarrollar una aplicación capaz <strong>de</strong> cargar dinámicamente<br />

un módulo (implementado como una biblioteca dinámica<br />

con extensión .so) que contendrá la <strong>de</strong>scripción <strong>de</strong> un plugin.<br />

Este plugin contendrá una serie <strong>de</strong> funciones <strong>de</strong> control, que <strong>de</strong>berán<br />

ejecutarse bien como un proceso o bien como un thread<br />

controlado por el programa cargador.<br />

La aplicación, llamada cargador, se implementará como un proceso<br />

con la capacidad <strong>de</strong> cargar un módulo que contiene la implementación<br />

<strong>de</strong> un plugin, arrancar instancias <strong>de</strong>l mismo y controlar<br />

su ejecución (<strong>de</strong>tener, reanudar y finalizar su ejecución), usando<br />

para ello mecanismos <strong>de</strong> control <strong>de</strong> procesos y <strong>de</strong> threads, tales como<br />

señales o mecanismos <strong>de</strong> sincronización específicos <strong>de</strong> procesos<br />

ligeros.<br />

4.2. Descripción<br />

4.2.1. Uso <strong>de</strong> la aplicación: El programa “cargador” se invocará<br />

<strong>de</strong>s<strong>de</strong> el intérprete <strong>de</strong> mandatos (shell) indicándole un argumento<br />

que parametriza su funcionamiento. El objeto general <strong>de</strong>l<br />

programa es controlar y manipular la ejecución <strong>de</strong> un plugin.<br />

Si por cualquier motivo, alguna operación no se pue<strong>de</strong> realizar<br />

(por ejemplo, cargar el módulo dinámico), el programa<br />

sacará por el error estándar un mensaje con el formato:<br />

"%s:␣Error(%d),␣%s\n" don<strong>de</strong>:<br />

❒ ␣ es un espacio en blanco.<br />

❒ El primer campo ( %s) es el nombre completo <strong>de</strong>l plugin que<br />

ha generado el error (arg).<br />

❒ El segundo campo ( %d) es el código <strong>de</strong> error (ver sección<br />

4.3.7).<br />

(23)


SO #<strong>2013</strong>/1 Revisión 12.1<br />

❒ El último campo ( %s) es el texto <strong>de</strong>l mensaje <strong>de</strong> error generado.<br />

El programa terminará por medio <strong>de</strong> la llamada exit(int), indicando<br />

el código <strong>de</strong> error <strong>de</strong> la operación que dio error ó 0 si la<br />

operación no dio problemas. Los códigos <strong>de</strong> error que se pue<strong>de</strong>n<br />

dar en cada operación vienen indicados en los siguientes apartados.<br />

4.2.2. Sintaxis <strong>de</strong> la ĺınea <strong>de</strong> mandato <strong>de</strong>l programa: La estructura<br />

general <strong>de</strong> una llamada a cargador se encuentra recogida<br />

en ✞ la siguiente estructura:<br />

☎<br />

cargador opción [fichero mandatos]<br />

✝<br />

✆<br />

El primer argumento <strong>de</strong>termina el tipo <strong>de</strong> mecanismo que se va<br />

a usar para la ejecución <strong>de</strong>l plugin, que <strong>de</strong>berá soportar tanto el<br />

uso <strong>de</strong> procesos convencionales (opción -p) como el <strong>de</strong> procesos<br />

ligeros, threads, (opción -t).<br />

El segundo argumento, que es opcional, permite cargar un fichero<br />

<strong>de</strong> mandatos a ejecutar por el programa cargador. En el caso<br />

<strong>de</strong> proporcionarle este fichero, el funcionamiento <strong>de</strong>l programa<br />

será en “modo batch”, cargando los mandatos <strong>de</strong>l fichero como si<br />

se hubiesen proporcionado por línea <strong>de</strong> mandatos.<br />

4.2.3. Conceptos: A efectos aclaratorios, resulta necesario distinguir<br />

entre:<br />

❒ Módulo plugin: Biblioteca dinámica que contiene el código<br />

<strong>de</strong> un plugin. El programa cargador sólo pue<strong>de</strong> tener un<br />

módulo cargado por ejecución.<br />

❒ Instancia <strong>de</strong>l plugin: El código <strong>de</strong> un plugin cuando<br />

está en ejecución. El programa cargador pue<strong>de</strong> lanzar más<br />

<strong>de</strong> una instancia por ejecución <strong>de</strong>l programa, pudiendo haber<br />

varias <strong>de</strong> estas instancias arrancadas y en ejecución a<br />

(24)


01/02/<strong>2013</strong> SO #<strong>2013</strong>/1<br />

la vez. También pue<strong>de</strong> haber arrancada una sola instancia<br />

en cada momento, pero una misma ejecución <strong>de</strong>l programa<br />

cargador pue<strong>de</strong> arrancar y finalizar varias instancias antes<br />

<strong>de</strong> terminar.<br />

4.3. Acciones <strong>de</strong>l mandato<br />

El mandato cargador <strong>de</strong>berá realizar las siguientes acciones:<br />

➀ Funcionamiento básico<br />

➁ Carga <strong>de</strong>l módulo <strong>de</strong> plugin<br />

➂ Arranque y finalización usando procesos<br />

➃ Arranque y finalización usando threads<br />

➄ Parada y re-arranque en procesos y threads.<br />

➅ Gestión <strong>de</strong> varias instancias <strong>de</strong> procesos/threads.<br />

4.3.1. Funcionamiento básico: El programa cargador, al arrancarse<br />

en modo interactivo (sin el segundo argumento <strong>de</strong> fichero <strong>de</strong><br />

mandatos), muestra un prompt que permite al usuario ir dictándole<br />

ór<strong>de</strong>nes, en forma <strong>de</strong> mandatos, para el cargador. Si se trata <strong>de</strong><br />

una ejecución con fichero <strong>de</strong> mandatos, estas ór<strong>de</strong>nes se leerán <strong>de</strong>l<br />

fichero indicado como segundo argumento.<br />

Ejecución interactiva:<br />

[usuario@maquina ~] cargador -t<br />

cargador> echo Hola mundo<br />

Hola Mundo<br />

✿✿✿✿✿✿✿✿✿✿✿✿✿<br />

cargador> quit<br />

(25)


SO #<strong>2013</strong>/1 Revisión 12.1<br />

Ejecución con fichero <strong>de</strong> mandatos:<br />

[usuario@maquina ~] cargador -t or<strong>de</strong>nes<br />

Hola Mundo<br />

✿✿✿✿✿✿✿✿✿✿✿✿✿<br />

En cualquiera <strong>de</strong> los casos, el código <strong>de</strong> apoyo facilitado al alumno<br />

proporciona la estructura básica para manipular estas dos formas<br />

<strong>de</strong> introducir ór<strong>de</strong>nes al programa cargador. Esta estructura básica<br />

invocará una función distinta para cada uno <strong>de</strong> los diferentes<br />

tipos <strong>de</strong> mandatos. Es tarea <strong>de</strong>l alumno implementar cada una <strong>de</strong><br />

estas funciones.<br />

Este primer apartado incluye la implementación <strong>de</strong> los tres mandatos<br />

más sencillos:<br />

➊ Mandato <strong>de</strong> salida:<br />

Mandato <strong>de</strong> Salida:<br />

echo mensaje<br />

Este mandato <strong>de</strong>be sacar por la salida estándar <strong>de</strong> error el<br />

mensaje que aparece a continuación <strong>de</strong>l propio mandato.<br />

➋ Mandato <strong>de</strong> espera:<br />

Mandato <strong>de</strong> Espera:<br />

sleep segundos<br />

Este mandato <strong>de</strong>be suspen<strong>de</strong>r la ejecución <strong>de</strong>l programa<br />

cargador, no <strong>de</strong> las instancias <strong>de</strong> plugins que estén ejecutándose,<br />

durante una serie <strong>de</strong> segundos (indicados como<br />

(26)


01/02/<strong>2013</strong> SO #<strong>2013</strong>/1<br />

argumento). Es obligatorio implementar este mandato por<br />

medio <strong>de</strong> la llamada al sistema nanosleep(2). Este mandato<br />

no <strong>de</strong>be generar mensaje alguno (ni por error ni por salida<br />

estándar) salvo en el caso especificado en la Sección 4.3.7).<br />

➌ Mandato <strong>de</strong> salida:<br />

Mandato <strong>de</strong> Salida:<br />

quit<br />

Este mandato termina la ejecución <strong>de</strong>l programa cargador<br />

y <strong>de</strong> todas las instancias <strong>de</strong> plugins que tenga en ejecución.<br />

El programa <strong>de</strong>be finalizar con un código <strong>de</strong> terminación 0<br />

si no hubo errores, o el código <strong>de</strong>l último error en caso <strong>de</strong><br />

haber habido alguno. Este mandato no <strong>de</strong>be generar mensaje<br />

alguno (ni por error ni por salida estándar).<br />

4.3.2. Carga básica <strong>de</strong>l módulo <strong>de</strong>l plugin: Esta parte implica<br />

la implementación <strong>de</strong>l mandato:<br />

Mandato <strong>de</strong> Carga:<br />

load módulo<br />

Este mandato carga el fichero indicado por el parámetro módulo.<br />

Para flexibilizar el uso <strong>de</strong> esta herramienta, los módulos que<br />

implementan los plugins se cargarán dinámicamente. Para ello, se<br />

sugiere el uso <strong>de</strong> las funcionalida<strong>de</strong>s <strong>de</strong> carga dinámica <strong>de</strong> bibliotecas<br />

(ver la llamada dlopen).<br />

El procedimiento para la carga <strong>de</strong> los plugins <strong>de</strong>be ser el siguiente:<br />

(27)


SO #<strong>2013</strong>/1 Revisión 12.1<br />

1. Se solicitará la apertura <strong>de</strong> la biblioteca dinámica.<br />

2. Se buscará en ella el símbolo plugin info (el símbolo buscado<br />

se correspon<strong>de</strong>rá con el nombre <strong>de</strong> una función que<br />

<strong>de</strong>vuelve una estructura con información <strong>de</strong>l módulo).<br />

3. Se ejecutará dicha función (obteniendo un puntero a dicha<br />

estructura <strong>de</strong> información).<br />

4. Finalmente, se guarda el puntero a esta estructura que contiene<br />

los punteros a todas las funciones <strong>de</strong>l plugin.<br />

La <strong>de</strong>finición <strong>de</strong>l prototipo <strong>de</strong> dicha función, así como la estructura<br />

<strong>de</strong>vuelta se encuentran <strong>de</strong>scritos en el fichero <strong>de</strong> apoyo<br />

plugin info.h. Los campos <strong>de</strong> la citada estructura son:<br />

type<strong>de</strong>f struct plugin info st {<br />

char* banner;<br />

void (*plugin loop) ();<br />

void (*plugin stop) ();<br />

void (*plugin resume) ();<br />

int (*plugin finish) ();<br />

} plugin info t;<br />

plugin info t* plugin info();<br />

La estructura que <strong>de</strong>vuelve plugin info incluye los siguientes<br />

campos:<br />

❒ banner: Es la ca<strong>de</strong>na <strong>de</strong> caracteres que i<strong>de</strong>ntifica al plugin.<br />

Cuando se tenga que indicar el nombre <strong>de</strong>l plugin se usará esta<br />

ca<strong>de</strong>na.<br />

❒ plugin loop: Es un puntero a una función que se invoca en<br />

cada una <strong>de</strong> las iteraciones <strong>de</strong>l bucle <strong>de</strong> ejecución <strong>de</strong>l plugin.<br />

En otras palabras, la ejecución <strong>de</strong>l plugin (en un proceso o<br />

en un thread) consistirá en un bucle infinito en el que se<br />

invoca a esta función.<br />

(28)


01/02/<strong>2013</strong> SO #<strong>2013</strong>/1<br />

❒ plugin stop: Es un puntero a una función que se invoca por<br />

parte <strong>de</strong>l plugin, cuando se haya solicitado una parada <strong>de</strong>l<br />

mismo.<br />

❒ plugin resume: Es un puntero a una función que se invoca<br />

cuando habiéndose <strong>de</strong>tenido previamente el plugin, se solicita<br />

que reanu<strong>de</strong> su ejecución.<br />

❒ plugin finish: Es un puntero a una función que se invoca<br />

cuando se finaliza una instancia en ejecución <strong>de</strong>l plugin.<br />

Este mandato <strong>de</strong>be verificar que se pue<strong>de</strong> cargar el módulo sin<br />

problemas, que existe el símbolo buscado y que se ejecuta correctamente.<br />

Para ello pue<strong>de</strong> dar lugar a dos tipos <strong>de</strong> errores diferentes<br />

(ver sección <strong>de</strong> errores, Sección 4.3.7).<br />

Si este mandato se ejecuta con éxito, <strong>de</strong>be mostrar el mensaje:<br />

“Modulo nombre módulo cargado correctamente” en una línea<br />

por el error estándar.<br />

4.3.3. Arranque y finalización usando procesos: Una vez cargado<br />

un módulo, y <strong>de</strong>pendiendo <strong>de</strong>l modo en el que se haya ejecutado<br />

el programa cargador es posible lanzar la ejecución <strong>de</strong><br />

una instancia <strong>de</strong>l plugin. Ésta se lanzará como un proceso si el<br />

programa cargador se ejecutó con la opción “-p”.<br />

Esta parte implica la implementación <strong>de</strong>l mandato:<br />

Mandato <strong>de</strong> arranque:<br />

start<br />

Este mandato lanza un nuevo proceso (usando el servicio fork <strong>de</strong>l<br />

sistema operativo), que ejecutará una instancia, que no es más que<br />

un bucle infinito <strong>de</strong> llamadas a la función plugin loop.<br />

(29)


SO #<strong>2013</strong>/1 Revisión 12.1<br />

El resultado <strong>de</strong> arrancar con éxito un plugin <strong>de</strong>be mostrar, por la<br />

salida <strong>de</strong> error estándar, dos mensajes, uno a continuación <strong>de</strong>l<br />

otro: “Módulo iniciado: instancia ” y “Numero <strong>de</strong> modulos<br />

iniciados: n instancias ”, cada uno <strong>de</strong> los mensajes en una<br />

línea diferente. El valor <strong>de</strong> instancia se correspon<strong>de</strong>rá a un número<br />

consecutivo que se dará a las mismas, cada vez que se llame<br />

al mandato start. Dicho número emprezará en cero (0) e<br />

irá incrementándose con cada uno <strong>de</strong> estos mandatos. El valor <strong>de</strong><br />

n instancia es el número <strong>de</strong> instancias que se han arrancado.<br />

✍ NOTA: Recuer<strong>de</strong> que en este caso sólo habrá una instancia<br />

en ejecución en cada momento, pero sí pue<strong>de</strong>n ejecutarse dos instancias<br />

en secuencia, primero una, finalizar su ejecución y luego<br />

otra.<br />

El mandato complementario al arranque <strong>de</strong> una instancia <strong>de</strong>l plugin<br />

es su finalización. Cuando una instancia esté en ejecución se<br />

pue<strong>de</strong> finalizar en cualquier momento. El proceso <strong>de</strong> finalización<br />

<strong>de</strong>be concluir la ejecución <strong>de</strong>l proceso que ha arrancado dicha instancia<br />

<strong>de</strong> forma inmediata, in<strong>de</strong>pendientemente <strong>de</strong> que se encuentre<br />

ejecutando <strong>de</strong>ntro <strong>de</strong> la función plugin loop.<br />

Para implementar este mecanismo <strong>de</strong> parada asíncrona se <strong>de</strong>ben<br />

utilizar señales, en concreto la señal SIGTERM. Dicha señal se <strong>de</strong>be<br />

mandar al proceso que ejecuta el bucle infinito <strong>de</strong> la instancia<br />

<strong>de</strong>l plugin. Al recibir la señal, y antes <strong>de</strong> finalizar el proceso, el<br />

propio proceso asociado a la instancia <strong>de</strong>be llamar a la función<br />

plugin finish, que le <strong>de</strong>vuelve un valor que es el que se usará como<br />

valor <strong>de</strong> la llamada exit con la que finalizará el proceso que<br />

ejecuta la instancia.<br />

Esta parte implica la implementación <strong>de</strong>l mandato:<br />

Mandato <strong>de</strong> finalización:<br />

finish instancia<br />

(30)


01/02/<strong>2013</strong> SO #<strong>2013</strong>/1<br />

El parámetro instancia es opcional y, en caso <strong>de</strong> no indicarse, se<br />

tomará el valor cero (0), primera instancia.<br />

Si el mandato <strong>de</strong> finalización tiene éxito, se <strong>de</strong>be <strong>de</strong>volver el mensaje:<br />

“Modulo finalizado: instancia (valor retorno )”, don<strong>de</strong><br />

instancia indica el número <strong>de</strong> instancia que ha finalizado y valor<br />

retorno es el valor <strong>de</strong> retorno que ha <strong>de</strong>vuelto la llamada exit<br />

<strong>de</strong>l proceso que ejecutaba la instancia y ha finalizado.<br />

Si el proceso que ejecutaba la instancia <strong>de</strong>l plugin finaliza con<br />

una señal, se <strong>de</strong>be generar el error correspondiente (ver sección <strong>de</strong><br />

errores, Sección 4.3.7).<br />

Ejemplo <strong>de</strong> uso:<br />

[usuario@maquina ~] cargador -p<br />

cargador> echo Comienzo<br />

Comienzo<br />

✿✿✿✿✿✿✿✿✿✿<br />

cargador> load modulo-foo.so<br />

Modulo modulo-foo.so cargado correctamente<br />

✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿<br />

cargador> start<br />

Modulo iniciado: 0<br />

✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿<br />

Numero <strong>de</strong> modulos iniciados: 1<br />

✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿<br />

cargador> sleep 3<br />

cargador> finish<br />

Modulo finalizado: 0 (4)<br />

✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿<br />

cargador> quit<br />

4.3.4. Arranque y finalización usando threads: Esta parte <strong>de</strong><br />

la práctica es análoga a la anterior, pero utilizando procesos ligeros,<br />

threads, en lugar <strong>de</strong> procesos normales. Los mandatos usados<br />

son realmente los mismos que en el caso <strong>de</strong> los procesos, diferenciándose<br />

en que el programa cargador se <strong>de</strong>be ejecutar con la<br />

opción “-t”.<br />

El comportamiento <strong>de</strong>be ser idéntico al caso <strong>de</strong> los procesos, pe-<br />

(31)


SO #<strong>2013</strong>/1 Revisión 12.1<br />

ro con threads, utilizando también la misma señal SIGTERM para<br />

finalizar la ejecución, esta vez, <strong>de</strong>l thread.<br />

4.3.5. Parada y re-arranque: Cuando una instancia está en ejecución,<br />

el estado <strong>de</strong> esta ejecución <strong>de</strong>be po<strong>de</strong>r manipularse mediante<br />

una serie <strong>de</strong> mandatos. La manipulación que se va a realizar<br />

consiste en la posibilidad <strong>de</strong> <strong>de</strong>tener y <strong>de</strong> reanudar la ejecución.<br />

A diferencia <strong>de</strong>l proceso <strong>de</strong> finalización antes visto, la operación<br />

<strong>de</strong> parada no es inmediata sino que se espera a que se finalice la<br />

llamada en curso <strong>de</strong> la función plugin loop. Como se ha comentado,<br />

el flujo <strong>de</strong> ejecución <strong>de</strong>l proceso/thread asociado a la instancia<br />

es un bucle infinito que llama <strong>de</strong> forma repetida a esta función. La<br />

or<strong>de</strong>n <strong>de</strong> parada sólo se hará efectiva al final <strong>de</strong> una ejecución <strong>de</strong><br />

esta función, si se ha solicitando durante la ejecución <strong>de</strong> la misma<br />

y no ha sido revocada por una or<strong>de</strong>n <strong>de</strong> re-arranque antes <strong>de</strong> ello.<br />

Una vez solicitada la parada <strong>de</strong> la instancia, ésta se quedará bloquedada<br />

hasta que se solicite una operación <strong>de</strong> re-arranque.<br />

Justo antes <strong>de</strong> <strong>de</strong>tener un proceso, el proceso/thread que ejecuta<br />

la instancia <strong>de</strong>berá llamar a la función plugin stop. Asimismo,<br />

<strong>de</strong>spués <strong>de</strong> re-arrancar y antes <strong>de</strong> entrar <strong>de</strong> nuevo en el bucle <strong>de</strong><br />

llamadas a plugin loop, el proceso/thread que ejecuta la instancia<br />

<strong>de</strong>berá llamar a la función plugin resume.<br />

La or<strong>de</strong>n <strong>de</strong> parada <strong>de</strong> la instancia se realiza por medio <strong>de</strong>l mandato:<br />

Mandato <strong>de</strong> parada:<br />

stop instancia<br />

El parámetro instancia es opcional y, en caso <strong>de</strong> no indicarse, se<br />

tomará el valor cero (0), primera instancia.<br />

(32)


01/02/<strong>2013</strong> SO #<strong>2013</strong>/1<br />

Cuando se ejecuta el mandato <strong>de</strong> parada, se <strong>de</strong>be <strong>de</strong>volver el mensaje:<br />

“Modulo <strong>de</strong>tenido: instancia ”, don<strong>de</strong> instancia indica el<br />

número <strong>de</strong> instancia que se ha parado.<br />

La or<strong>de</strong>n <strong>de</strong> re-arranque <strong>de</strong> la instancia se realiza por medio <strong>de</strong>l<br />

mandato:<br />

Mandato <strong>de</strong> re-arranque:<br />

resume instancia<br />

El parámetro instancia es opcional y, en caso <strong>de</strong> no indicarse, se<br />

tomará el valor cero (0), primera instancia.<br />

Cuando se ejecuta el mandato <strong>de</strong> parada, se <strong>de</strong>be <strong>de</strong>volver el mensaje:<br />

“Modulo reiniciado: instancia ”, don<strong>de</strong> instancia indica<br />

el número <strong>de</strong> instancia que se ha parado.<br />

La implementación <strong>de</strong> esta funcionalidad sí que es diferente en el<br />

caso <strong>de</strong> threads y procesos, <strong>de</strong>bido a la compartición o no <strong>de</strong> espacio<br />

<strong>de</strong> memoria común. Por ello, se exige que la implementación<br />

<strong>de</strong> estos dos mandatos siga las siguientes restricciones:<br />

❒ Threads: La solicitud <strong>de</strong> parada y re-arranque se <strong>de</strong>be realizar<br />

por medio <strong>de</strong> mecanismos <strong>de</strong> sincronización entre threads,<br />

es <strong>de</strong>cir mutex y variables condicionales.<br />

❒ Procesos: La solicitud <strong>de</strong> parada se realizará por medio<br />

<strong>de</strong>l envío <strong>de</strong> la señal SIGUSR1, mientras que la or<strong>de</strong>n <strong>de</strong> rearranque<br />

se realizará por medio <strong>de</strong> la señal SIGCONT. A pesar<br />

<strong>de</strong> utilizar señales, se recuerda que la or<strong>de</strong>n <strong>de</strong> parada no se<br />

<strong>de</strong>be ejecutar inmediatamente, sino que se <strong>de</strong>be diferir su<br />

efecto al momento en el que se haya terminado <strong>de</strong> ejecutar<br />

la llamada a la función plugin loop, es <strong>de</strong>cir una vez por<br />

iteración <strong>de</strong>l bucle.<br />

(33)


SO #<strong>2013</strong>/1 Revisión 12.1<br />

Un ejemplo <strong>de</strong> uso (válido tanto para procesos como para threads)<br />

es: Ejemplo <strong>de</strong> uso:<br />

[usuario@maquina ~] cargador -t<br />

cargador> echo Comienzo<br />

Comienzo<br />

✿✿✿✿✿✿✿✿✿✿<br />

cargador> load modulo-foo.so<br />

Modulo modulo-foo.so cargado correctamente<br />

✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿<br />

cargador> start<br />

Modulo iniciado: 0<br />

✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿<br />

Numero <strong>de</strong> modulos iniciados: 1<br />

✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿<br />

cargador> sleep 2<br />

cargador> stop<br />

Modulo <strong>de</strong>tenido: 0<br />

✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿<br />

cargador> sleep 2<br />

cargador> resume<br />

Modulo reiniciado: 0<br />

✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿<br />

cargador> finish<br />

Modulo finalizado: 0 (4)<br />

✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿<br />

cargador> quit<br />

4.3.6. Gestión <strong>de</strong> varias instancias: El último <strong>de</strong> los apartados<br />

observa la gestión <strong>de</strong> más <strong>de</strong> una instancia en ejecución al mismo<br />

tiempo. Se podrá invocar varias veces el mandato start sin<br />

necesidad <strong>de</strong> haber hecho un finish <strong>de</strong> la instancia correspondiente<br />

y el programa cargador <strong>de</strong>berá ser capaz <strong>de</strong> lanzar varios<br />

procesos/threads a la vez.<br />

Para la gestión a<strong>de</strong>cuada <strong>de</strong> estos procesos, resulta indispensable<br />

que los mandatos <strong>de</strong> stop, resume y finish incluyan el parámetro<br />

adicional que i<strong>de</strong>ntifica sobre qué instancia se aplican.<br />

Las ór<strong>de</strong>nes <strong>de</strong> parada y re-arranque se <strong>de</strong>ben aplicar a nivel <strong>de</strong><br />

instancia (se <strong>de</strong>tiene o se reanuda la ejecución <strong>de</strong> cada instancia<br />

(34)


01/02/<strong>2013</strong> SO #<strong>2013</strong>/1<br />

por separado).<br />

✍ NOTA: El comportamiento <strong>de</strong> varias instancias en ejecución<br />

pue<strong>de</strong> ser diferente si se lanzan como threads o como procesos, <strong>de</strong>pendiendo<br />

<strong>de</strong>l uso <strong>de</strong> variables globales o no por parte <strong>de</strong>l módulo<br />

que <strong>de</strong>fine el plugin. Si éste <strong>de</strong>fine una variable global en su implementación,<br />

dicha variable estará compartida en la versión <strong>de</strong><br />

threads y no en la <strong>de</strong> procesos.<br />

Esta indicación <strong>de</strong>pen<strong>de</strong> <strong>de</strong> la librería que <strong>de</strong>fine el módulo, que<br />

el alumno no tiene que modificar, pero ese comportamiento <strong>de</strong>be<br />

tenerse en cuenta a la hora <strong>de</strong> usar variables globales o no en el<br />

código <strong>de</strong>l programa cargador.<br />

Un ejemplo <strong>de</strong> uso (válido tanto para procesos como para threads)<br />

es:<br />

Ejemplo <strong>de</strong> uso:<br />

(35)


SO #<strong>2013</strong>/1 Revisión 12.1<br />

[usuario@maquina ~] cargador -p<br />

cargador> echo Comienzo<br />

Comienzo<br />

✿✿✿✿✿✿✿✿✿✿<br />

cargador> load modulo-foo.so<br />

Modulo modulo-foo.so cargado correctamente<br />

✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿<br />

cargador> start<br />

Modulo iniciado: 0<br />

✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿<br />

Numero <strong>de</strong> modulos iniciados: 1<br />

✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿<br />

cargador> sleep 1<br />

cargador> start<br />

Modulo iniciado: 1<br />

✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿<br />

Numero <strong>de</strong> modulos iniciados: 2<br />

✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿<br />

cargador> sleep 2<br />

cargador> stop 0<br />

Modulo <strong>de</strong>tenido: 0<br />

✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿<br />

cargador> sleep 2<br />

cargador> resume 0<br />

Modulo reiniciado: 0<br />

✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿<br />

cargador> finish 1<br />

Modulo finalizado: 1 (6)<br />

✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿<br />

cargador> finish 0<br />

Modulo finalizado: 0 (2)<br />

✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿<br />

cargador> quit<br />

4.3.7. Errores posibles: La ejecución <strong>de</strong> estos mandatos pue<strong>de</strong><br />

dar lugar a una serie <strong>de</strong> errores que <strong>de</strong>ben ser notificados por el<br />

programa cargador.<br />

(36)


01/02/<strong>2013</strong> SO #<strong>2013</strong>/1<br />

ERROR<br />

Código Mensaje<br />

1 No se pue<strong>de</strong> cargar<br />

Este error lo da cuando ha habido un problema<br />

en la carga <strong>de</strong>l fichero indicado como módulo.<br />

El error pue<strong>de</strong> ser tanto que el fichero no exista,<br />

como que no sea una biblioteca dinámica válida.<br />

ERROR<br />

Código Mensaje<br />

2 No se encuentra simbolo<br />

Este error aparece cuando, una vez cargado el fichero<br />

indicado como módulo, éste no contiene el<br />

símbolo plugin info, por lo tanto no se pue<strong>de</strong><br />

ejecutar para obtener la estructura <strong>de</strong> información<br />

<strong>de</strong>l plugin.<br />

ERROR<br />

Código Mensaje<br />

3 Parametro <strong>de</strong> mandato no valido<br />

Este error se da en todas las solicitu<strong>de</strong>s <strong>de</strong> mandatos<br />

que lleven asociado un parámetro, cuando<br />

dicho parámetro no es <strong>de</strong>l tipo a<strong>de</strong>cuado. Por<br />

ejemplo, si al mandato sleep se le pasa un argumento<br />

que no es un número entero.<br />

ERROR<br />

Código Mensaje<br />

4 Finalizacion anomala <strong>de</strong>l plugin<br />

Este error se produce cuando el thread/proceso<br />

correspondiente a una instancia finaliza <strong>de</strong> forma<br />

anómala (con una señal).<br />

(37)


SO #<strong>2013</strong>/1 Revisión 12.1<br />

ERROR<br />

Código Mensaje<br />

5 Error al crear instancia<br />

Este caso <strong>de</strong> error se obtiene cuando el arranque<br />

<strong>de</strong> una instancia <strong>de</strong>l plugin (tanto en threads como<br />

en procesos) <strong>de</strong> un error y no se llegue a crear<br />

el thread/proceso correspondiente.<br />

4.4. Páginas <strong>de</strong>l manual a consultar<br />

A título <strong>de</strong> ayuda se recomienda la consulta <strong>de</strong> las siguientes funciones<br />

o llamadas en las páginas <strong>de</strong>l manual. Dichas páginas se<br />

pue<strong>de</strong>n consultar vía el mandato man:<br />

❒ nanosleep(2)<br />

❒ dlopen(3)<br />

❒ dlsym(3)<br />

❒ dlclose(3)<br />

❒ waitpid(2)<br />

❒ fork(2)<br />

❒ sigaction(2)<br />

❒ kill(2)<br />

❒ pause(2)<br />

❒ strtol(3) / atoi(3)<br />

❒ pthread create(3)<br />

❒ pthread exit(3)<br />

(38)


01/02/<strong>2013</strong> SO #<strong>2013</strong>/1<br />

❒ pthread join(3)<br />

❒ pthread mutex init(3)<br />

❒ pthread mutex lock(3)<br />

❒ pthread mutex unlock(3)<br />

❒ pthread mutex <strong>de</strong>stroy(3)<br />

❒ pthread cond init(3)<br />

❒ pthread cond <strong>de</strong>stroy(3)<br />

❒ pthread cond signal(3)<br />

❒ pthread cond wait(3)<br />

❒ pthread kill(3)<br />

(39)


SO #<strong>2013</strong>/1 Revisión 12.1<br />

5. Servidor - Implementación <strong>de</strong>l servidor <strong>de</strong> un pseudo-<br />

FTP<br />

5.1. Objetivos<br />

El alumno <strong>de</strong>be <strong>de</strong>sarrollar una implementación <strong>de</strong> un sencillo servidor<br />

<strong>de</strong> un protocolo simplificado <strong>de</strong> tipo FTP, para transferencia<br />

<strong>de</strong> ficheros por medio <strong>de</strong> sockets.<br />

5.2. Descripción<br />

5.2.1. Uso <strong>de</strong> la aplicación: El programa “servidor” se invocará<br />

<strong>de</strong>s<strong>de</strong> el intérprete <strong>de</strong> mandatos (shell), este programa no<br />

recibe ningún parámetro y, al ponerlo a ejecutar, se <strong>de</strong>be quedar a<br />

la espera <strong>de</strong> peticiones por parte <strong>de</strong> uno o varios clientes, <strong>de</strong> forma<br />

secuencial.<br />

5.2.2. Sintaxis <strong>de</strong> la ĺınea <strong>de</strong> mandato <strong>de</strong>l programa: La estructura<br />

general <strong>de</strong> una llamada a servidor se encuentra recogida<br />

en ✄ la siguiente estructura:<br />

✂servidor<br />

✁<br />

Como ya se ha dicho, este programa no recibe ningún parámetro.<br />

5.3. Apartados<br />

5.3.1. Funcionamiento básico: El servidor se encuentra inicialmente<br />

escuchando mensajes por un puerto UDP. Los mensajes<br />

representan solicitu<strong>de</strong>s <strong>de</strong> transferencia <strong>de</strong> ficheros. Las transferencias,<br />

en esta versión simplificada <strong>de</strong>l servidor FTP siempre se<br />

harán <strong>de</strong>l servidor hacia el cliente. El cliente transmite un mensaje<br />

en el cual indica la operación a realizar y el nombre <strong>de</strong>l fichero<br />

original (en el servidor) y el nombre local (en el cliente).<br />

El servidor respon<strong>de</strong> con la misma estructura <strong>de</strong> mensaje (vía<br />

UDP también) indicando si se pue<strong>de</strong> realizar o no la operación<br />

(40)


01/02/<strong>2013</strong> SO #<strong>2013</strong>/1<br />

(<strong>de</strong>pendiendo <strong>de</strong> que el fichero original exista o no) y, en el caso<br />

<strong>de</strong> ser posible la transferencia, el puerto TCP que se va a usar.<br />

La transmisión <strong>de</strong>l fichero se realiza a través <strong>de</strong> conexiones stream<br />

por medio <strong>de</strong> TCP.<br />

5.3.2. Descripción general <strong>de</strong>l protocolo: Una transferencia tipo<br />

entre cliente y servidor consta <strong>de</strong> los siguientes pasos:<br />

➀ El servidor arranca, reserva un puerto UDP y se queda a la<br />

escucha en él.<br />

➁ El cliente acce<strong>de</strong> a dicho puerto <strong>de</strong> servicio UDP y transmite<br />

un mensaje <strong>de</strong> tipo REQUEST indicando un nombre <strong>de</strong><br />

fichero en el servidor y el nombre local que se usará cuando<br />

se transfiera a local.<br />

➂ El servidor comprueba que el fichero existe. Si no existe respon<strong>de</strong><br />

con un mensaje <strong>de</strong> tipo ERROR.<br />

➃ Si el fichero existe, el servidor abre un puerto TCP y respon<strong>de</strong><br />

al cliente, usando el anterior puerto UDP con un mensaje<br />

<strong>de</strong> tipo OK, en el que incluye el número <strong>de</strong> puerto TCP que<br />

ha reservado (el cliente no lo conoce a priori).<br />

➄ El servidor se queda esperando en el nuevo puerto TCP y el<br />

cliente abre dicha conexión.<br />

➅ Por la conexión TCP establecida se transmite el contenido<br />

completo <strong>de</strong>l fichero.<br />

➆ El servidor cierra la conexión con el cliente y se queda, <strong>de</strong><br />

nuevo, esperando nuevos mensajes en el puerto UDP.<br />

(41)


SO #<strong>2013</strong>/1 Revisión 12.1<br />

5.3.3. Configuración y puertos: El servidor, que el alumno <strong>de</strong>be<br />

implementar, <strong>de</strong>be reservar dos puertos que estén libres, primero<br />

uno UDP y luego otro <strong>de</strong> tipo TCP. Para realizar esta reserva y<br />

asegurarse que se busca un puerto libre, se solicitará al sistema<br />

(en la llamada bind) el puerto 0. Dicho número <strong>de</strong> puerto indica<br />

al sistema que <strong>de</strong>be buscar un puerto libre cualquiera.<br />

✍ NOTA: No se <strong>de</strong>be ir probando puertos <strong>de</strong> forma secuencial<br />

hasta que uno esté libre. Se <strong>de</strong>be solicitar uno libre por medio<br />

<strong>de</strong> este número <strong>de</strong> puerto 0, y luego se <strong>de</strong>be consultar cuál es el<br />

número <strong>de</strong> puerto asignado (ver llamada getsockname)<br />

La forma mediante la cual se notifica al cliente el puerto utilizado<br />

es diferente para cada tipo (UDP y TCP, en este programa):<br />

❒ Puerto UDP: En un caso real estos puertos son puertos<br />

estándar, pero, para permitir que varios usuarios ejecuten<br />

servidores en la misma máquina, se asigna buscando un puerto<br />

UDP cualquiera que esté libre y el servidor escribe en un<br />

fichero el número <strong>de</strong> puerto usado. El cliente lee este fichero<br />

y así sabe qué puerto es el <strong>de</strong>l servidor. Hay que tener<br />

en cuenta que este mecanismo es un poco artificial, pero<br />

permite que se ejecuten prácticas in<strong>de</strong>pendientes en la misma<br />

máquina. El código <strong>de</strong> apoyo incluye la función para<br />

escribir este fichero y que lo pueda leer el cliente (función<br />

Escribir Puerto).<br />

❒ Puerto TCP: Por su parte, el puerto TCP se notifica como<br />

respuesta válida <strong>de</strong>l servidor a una petición <strong>de</strong> transferencia.<br />

Cuando se comprueba que se pue<strong>de</strong> hacer la transferencia se<br />

transmite el número <strong>de</strong> puerto TCP que se va a usar.<br />

5.3.4. Estructura <strong>de</strong> los mensajes UDP: Todos los mensajes<br />

intercambiados entre cliente y servidor por medio <strong>de</strong> UDP se basan<br />

en la estructura UDP Msg. Dicha estructura, <strong>de</strong>scrita en el fichero<br />

message.h, contiene los siguientes campos:<br />

(42)


01/02/<strong>2013</strong> SO #<strong>2013</strong>/1<br />

type<strong>de</strong>f struct UDP Msg st {<br />

int op; /* Operación */<br />

char local[128]; /* Fichero local */<br />

char remoto[128]; /* Fichero remoto */<br />

int puerto; /* Puerto <strong>de</strong>l servidor para la transmisi<br />

<strong>de</strong>l fichero vía TCP */<br />

} UDP Msg;<br />

El campo op pue<strong>de</strong> tomar los siguientes valores:<br />

❒ REQUEST: Petición <strong>de</strong>l cliente <strong>de</strong> una transferencia.<br />

❒ OK: Respuesta afirmativa <strong>de</strong>l servidor, el fichero existe y se<br />

pue<strong>de</strong> hacer la transferencia.<br />

❒ ERROR: Respuesta negativa <strong>de</strong>l servidor, el fichero no existe<br />

y no se pue<strong>de</strong> hacer la transferencia.<br />

❒ QUIT: Petición <strong>de</strong>l cliente para que el servidor finalice su<br />

ejecución.<br />

Los campos local y remoto sólo tienen sentido en el mensaje<br />

REQUEST <strong>de</strong>l cliente al servidor. Indican el nombre <strong>de</strong>l fichero local<br />

(para el cliente) y remoto (<strong>de</strong>l servidor). La transmisión siempre<br />

es <strong>de</strong>l servidor hacia el cliente.<br />

El campo puerto es el que rellena el servidor en la respuesta OK<br />

y en dicho campo se indica el puerto TCP reservado.<br />

5.3.5. Traza <strong>de</strong> ejecución esperada en el servidor: Para comprobar<br />

que el servidor está funcionando correctamente, y <strong>de</strong>tectar<br />

eventuales errores, se exige una secuencia <strong>de</strong> trazas (impresas por<br />

la salida estándar <strong>de</strong>l programa servidor) estricta.<br />

(43)


SO #<strong>2013</strong>/1 Revisión 12.1<br />

Dicha secuencia es la siguiente: Ejemplo <strong>de</strong> trazas:<br />

[usuario@maquina ~] servidor<br />

SERVIDOR: Creacion <strong>de</strong>l socket UDP: OK<br />

SERVIDOR: Asignacion <strong>de</strong>l puerto servidor: OK<br />

SERVIDOR: Puerto guardado en fichero<br />

./puerto servidor: OK<br />

SERVIDOR: Creacion <strong>de</strong>l socket TCP: OK<br />

SERVIDOR: Asignacion <strong>de</strong>l puerto servidor: OK<br />

SERVIDOR: Aceptacion <strong>de</strong> peticiones: OK<br />

SERVIDOR: Puerto TCP reservado: OK<br />

SERVIDOR: Esperando mensaje.<br />

SERVIDOR: Mensaje <strong>de</strong>l cliente: OK<br />

SERVIDOR: REQUEST(prueba.txt.local,prueba.txt)<br />

SERVIDOR: Enviando <strong>de</strong>l resultado [OK]: OK<br />

SERVIDOR: Llegada <strong>de</strong> un mensaje: OK<br />

Cada mensaje se producirá tras la ejecución <strong>de</strong> una <strong>de</strong> las operaciones<br />

principales <strong>de</strong>l servidor, y se indicará si ha funcionado o<br />

no.<br />

❒ SERVIDOR: Creacion <strong>de</strong>l socket tipo : Tras la creación<br />

<strong>de</strong>l socket <strong>de</strong>l tipo correspondiente (UDP o TCP).<br />

❒ SERVIDOR: Asignacion <strong>de</strong>l puerto servidor: Tras finalizar<br />

la reserva <strong>de</strong>l puerto (ver bind). Debe haber dos trazas<br />

<strong>de</strong> este tipo en el servidor una por tipo <strong>de</strong> puerto (TCP o<br />

UDP) usado.<br />

❒ SERVIDOR: Aceptacion <strong>de</strong> peticiones: Después <strong>de</strong> haber<br />

invocado listen.<br />

❒ SERVIDOR: Puerto TCP reservado: Una vez finalizada la<br />

creación y reserva <strong>de</strong>l socket TCP.<br />

(44)


01/02/<strong>2013</strong> SO #<strong>2013</strong>/1<br />

❒ SERVIDOR: Esperando mensaje: Antes <strong>de</strong> quedarse bloqueado<br />

en una recepción <strong>de</strong> mensaje UDP.<br />

❒ SERVIDOR: Mensaje <strong>de</strong>l cliente: Después <strong>de</strong> recibir un<br />

mensaje UDP.<br />

❒ SERVIDOR: Enviando <strong>de</strong>l resultado [mensaje ]: Envio <strong>de</strong>l<br />

mensaje <strong>de</strong> respuesta correspondiente (OK o ERROR) al cliente.<br />

❒ SERVIDOR: Llegada <strong>de</strong> un mensaje: Antes <strong>de</strong> quedarse<br />

bloqueado en la espera <strong>de</strong> una conexión TCP (ver accept).<br />

5.3.6. Finalización <strong>de</strong>l servidor: Para finalizar la ejecución <strong>de</strong>l<br />

servidor, el cliente pue<strong>de</strong> mandar un mensaje <strong>de</strong> tipo QUIT en lugar<br />

<strong>de</strong> una petición REQUEST) <strong>de</strong> un fichero. Tras la recepción <strong>de</strong> este<br />

mensaje el servidor <strong>de</strong>be terminar su ejecución.<br />

5.3.7. Código <strong>de</strong> apoyo: En este programa, el código <strong>de</strong> apoyo<br />

proporcionado contiene algún elemento más que o habitual en los<br />

otros programas. El código <strong>de</strong> apoyo incluye:<br />

❒ cliente.c: En el subdirectorio Cliente se incluye una implementación<br />

<strong>de</strong> un cliente para el protocolo propuesto. Esta<br />

implementación no se <strong>de</strong>be modificar, pero conviene<br />

consultarla para ver el tipo <strong>de</strong> interacción que espera la otra<br />

parte <strong>de</strong>l protocolo.<br />

❒ message.h: Define el prototipo <strong>de</strong> estructura intercambiada<br />

por medio <strong>de</strong> los mensajes UDP, así como varias constantes<br />

usadas, tanto por cliente como por servidor.<br />

❒ lanzador.sh: Un sencillo script <strong>de</strong> apoyo que permite arrancar<br />

una instancia <strong>de</strong>l servidor y toda una batería <strong>de</strong> clientes<br />

que soliciten transferencia <strong>de</strong> ficheros. Este script es especialmente<br />

útil para automatizar ciertas pruebas.<br />

(45)


SO #<strong>2013</strong>/1 Revisión 12.1<br />

5.4. Páginas <strong>de</strong>l manual a consultar<br />

A título <strong>de</strong> ayuda se recomienda la consulta <strong>de</strong> las siguientes funciones<br />

o llamadas en las páginas <strong>de</strong>l manual. Dichas páginas se<br />

pue<strong>de</strong>n consultar vía el mandato man:<br />

❒ socket(2)<br />

❒ bind(2)<br />

❒ accept(2)<br />

❒ listen(2)<br />

❒ connect(2)<br />

❒ getsockname(2)<br />

❒ sendto(2)<br />

❒ recvfrom(2)<br />

❒ send(2)<br />

❒ recv(2)<br />

❒ exit(2)<br />

(46)


01/02/<strong>2013</strong> SO #<strong>2013</strong>/1<br />

Registro <strong>de</strong> Revisiones<br />

Este documento ha sido publicado como informe docente número<br />

<strong>2013</strong>/1 por el Departamento <strong>de</strong> Arquitectura y Tecnología <strong>de</strong> Sistemas<br />

Informáticos <strong>de</strong> la Facultad <strong>de</strong> Informática <strong>de</strong> la Universidad<br />

Politécnica <strong>de</strong> Madrid como parte <strong>de</strong> la asignatura Sistemas Operativos.<br />

El histórico <strong>de</strong> revisiones realizadas a este documento son:<br />

• Revisión 12.1 (01/02/<strong>2013</strong>). Versión completa<br />

• Versión inicial (20/01/2006).<br />

Este documento se encuentra actualmente mantenido por: Angel<br />

Rodríguez. c○ Departamento <strong>de</strong> Arquitectura y Tecnología <strong>de</strong> Sistemas<br />

Informáticos, Facultad <strong>de</strong> Informática.<br />

(47)

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!