(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
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)