Laboratorio No 3
Proyecto No1
Construyendo una
Shell Unix
Fecha de inicio: Lunes,
26 de marzo, 2006
Fecha de entrega: Lunes,
2 de abril, 2006
Objetivos
-
Fomentar en
los estudiantes el desarrollo de habilidades en programación en C o C++
-
Introducir a
los estudiantes en el manejo de procesos concurrentes en Unix, creación,
ejecución y terminación usando llamadas a sistemas fork(), exec() y wait()
-
Desarrollar
habilidades simples con control y comunicación de procesos concurrentes usando
señales.
-
Desarrollar habilidades
simples con comunicación entre procesos usando pipes
Metodología
Trabajo en grupo de 2
personas. Al final de la primera sesión los grupos deberán enviar su código
para evaluar el avance del proyecto. En la siguiente sesión se realizará la revisión
del proyecto.
Descripción
En este laboratorio los estudiantes desarrollarán
un intérprete de comandos simple en Unix (shell). La shell a implementar será
similar a las disponibles para Unix. La shell que usted implementará constará de dos partes de
implementación y una de prueba y análisis.
Parte 1
– Comandos simples
La shell debe proporcionar un prompt, lo que
identifica el modo de espera de comandos de la shell. Luego, debe leer un
comando desde teclado y parsear la entrada para identificar el comando y sus
argumentos. Finalmente debe ejecutar el comando ingresado en un proceso
concurrente, para lo cual debe usar el llamado a sistema fork() y algunas de
las variantes de exec(). Los comandos a soportar son ejecutados en foreground,
es decir, la shell ejecuta y espera por el término de su ejecución antes de
imprimir el promtp para esperar por el siguiente comando. La correcta
implementación de esta etapa lo hace merecedor de un 30% de la nota.
Nota: Si se presiona <enter> sin previo
comando, la shell simplemente imprime nuevamente el prompt.
Ejemplo
shellABC$> ls -l
total 116
-rwxr-xr-x 1 chernand profes 12299 2006-03-17 10:44 alarma
-rw-r--r-- 1 chernand profes 855 2006-03-17 10:44 alarma.c
-rwxr-xr-x 1 chernand profes 13084 2006-03-17 10:35 sigcomm
-rw-r--r-- 1 chernand profes 1733 2006-03-17 10:35 sigcomm.c
-rwxr-xr-x 1 chernand profes 11980 2006-03-17 10:26 sigerror
-rw-r--r-- 1 chernand profes 354 2006-03-17 10:26 sigerror.c
-rwxr-xr-x 1 chernand profes 12166 2006-03-17 10:30 sigfault
-rw-r--r-- 1 chernand profes 496 2006-03-17 10:30 sigfault.c
-rw-r--r-- 1 chernand profes 1019 2006-03-17 09:58 sigplan2.c
-rwxr-xr-x
1 chernand profes 11990 2006-03-17 10:40 sigusuario
-rw-r--r--
1 chernand profes 528 2006-03-17
10:40 sigusuario.c
shellABC$>
Parte 2
– Comandos background
Agregar a la shell soporte para comandos en
background, comandos que se ejecutan asincrónicamente, es decir la shell
empieza a ejecutar comando, pero no espera por su término e imprime el prompt
para ejecutar el siguiente comando. Los comandos background se reconocen porque
terminan con un “&”. La implementación debe velar por el uso correcto de
las llamadas a sistema wait() y sigaction() para que el proceso padre en la
shell reciba las señales de término de los comandos en background. Cuando un
proceso en background termina la shell debe imprimir “comando xxx terminó”. En
particular, la implementación de su shell deber considerar que el usuario puede
finalizar la shell con el comando exit, pero sólo lo puede realizar si no tiene
procesos en background ejecutándose. La correcta implementación de esta etapa
lo hace merecedor de un 30 % de la nota.
Ejemplo
shellABC$> sleep 10 &
[1] 23831
shellABC$>
Parte 3
- Filtros
Agregar a la shell soporte de filtros simples
usando pipes. Para su implementación utilice los llamados a sistema pipe() y
dup2() para crear un pipe y redirigir la salida y entrada estándar. La correcta
implementación de esta etapa lo hace merecedor de un 30% de la nota.
Ejemplo
shellABC$> ls –l | grep “lab”
Análisis
Pruebe su shell con una serie de comandos de Unix,
analice los casos en los cuales los comandos no son correctamente ejecutados.
Escriba en una o dos páginas los resultados de su análisis, incluyendo los
comandos y razones por las cuales su shell no es exitosa. Un correcto análisis
lo hace merecedor de un 10% de la nota.
Un ejemplo de programa usando fork, exec, waitpid
se encuentra disponible aquí.
Algunas Pistas
-
Use el
llamado a sistema waitpid(), en lugar de wait(). waitpid() le permite al
proceso padre esperar por un hijo específico en forma sincrónica o bien esperar
por cualquiera de sus hijos asincrónicamente. Para el segundo caso use la opción
WNOHANG y -1 en el parámetro de pid del hijo. Para mayor información vea el
manual en línea
-
Para hacer el
parsing del comando y sus argumentos puede usar alguna(s) de las siguientes index(),
rindex(), strspn(), strcspn(), strtok().
-
Use sigaction
y señal SIGCHLD. Si tiene algún problema con un error de “Interrumpted System
Call” use el flag SA_RESTART, en la estructura sigaction que defina. Vea el
manual en línea de sigaction para mayor información.
-
Si piensa
usar C++, piense en map<key, value> para almacenar los comandos
background