You are on page 1of 10

Objetivo

El objetivo de esta prctica es la programacin de un shell o intrprete de rdenes


simplificado que denominaremos minishell. Para llevar a cabo dicho objetivo ser
necesario trabajar con llamadas al sistema, en concreto con las responsables de gestin
de procesos y la gestin de seales.

1. Introduccin
1.1 Caractersticas de un shell
El shell o intrprete de rdenes es la interfaz primaria entre el usuario y el sistema
operativo en modo carcter. Un shell es un programa que lee una orden (o un fichero
con mltiples rdenes) introducida por un usuario, la analiza y la ejecuta. Para ello
realiza las llamadas al sistema que son necesarias para ejecutar una orden. La Figura 1
muestra un esquema bsico de los componentes de un sistema operativo.

Interfaz usuario

Shell Programas Entorno de ventanas


(KDE, Gnome)
Interfaz llamadas al sistema

Protocolos
Procesos Ficheros
de red

Memoria Drivers
Virtual
Interfaz hardware-software

CPU Memoria E/S Red

Figura 1. Estructura genrica de los componentes de un sistema operativo.


El shell posee una serie de caractersticas entre las que destacan:
rdenes internas y externas: Las rdenes internas estn implementadas en el
propio shell. Por ejemplo la orden cd y las relacionadas con gestin de
variables. Las rdenes externas estn implementadas en programas
independientes. El shell se encarga de buscar el programa y ejecutarlo pasando
los argumentos correspondientes
Redirecciones. Se permite redirigir la entrada o salida estndar a un fichero.
Tuberas (pipes). Permiten encadenar la ejecucin de varias rdenes.
Ejecucin en segundo plano (background). Permite ejecutar una orden sin que el
shell se quede bloqueado esperando su terminacin.
Variables. El shell permite definir y manejar variables de entorno ($PATH,
$HOME, etc).
Control de flujo: El shell permite su programacin con sentencias de control de
flujo.
Los usuarios pueden programar su propio shell dotndolo de mandatos ms o menos
complejos en funcin de sus necesidades. El shell o intrprete de rdenes de UNIX es
un programa ejecutable (como cualquier otro programa de usuario) que se encuentra

EUI-SG/INFOR.UVA.ES SO_PR02_20041012 1
disponible en cualquier entorno UNIX. Una estructura sencilla de un shell de UNIX
podra venir dado por el algoritmo que aparece en la Figura 2.

while (TRUE){
Imprimir_el_prompt();
Leer_ordenes_desde_teclado();
Analizar_orden_y_diferenciar_sus_campos();
Ejecutar_la_orden();
Figura 2. Estructura sencilla de un shell.
En la estructura sencilla del shell mostrada en la Figura 2, se pueden identificar los
mdulos bsicos que componen el shell. A continuacin se justifica la necesidad de
cada uno de los mdulos:
Imprimir_el _prompt(). Cuando aparece el prompt en la pantalla nos
indica que se est ejecutando el shell y que est preparado para que leer una
orden de teclado analizarla y ejecutarla.
Leer_ordenes_desde_teclado(). Es necesario leer la orden desde el
teclado.
Analizar_orden_y_diferenciar_sus_campos(). Una vez leda la
lnea ser necesario analizar de qu orden se trata y si tiene todos los argumentos
necesarios para su ejecucin interpretando correctamente cada uno de ellos.
Ejecutar_la _orden(). Para ejecutar la orden es probable que sea
necesario crear un nuevo proceso que ejecute el programa que contiene el cdigo
de dicha orden.
A pesar de la sencillez del esquema mostrado en la Figura 2, un shell es un programa
complejo porque ha de ser capaz de ejecutar un conjunto amplio de rdenes con
diferente nmero de argumentos, con redirecciones, etc. En las prcticas de SO se
tratar construir un shell reducido, capaz de ejecutar un nmero limitado de rdenes.
1.2 Sintaxis del minishell
Cualquiera de los intrpretes que vienen incluidos en una distribucin de UNIX (bash,
ksh, etc.) tiene una sintaxis para ejecutar rdenes bastante compleja lo cual los hace
programas bastante complicados de implementar. Para simplificar, el minishell que
desarrollaremos en esta prctica tendr limitado el conjunto de mandatos capaz de
ejecutar.
Para poder implementar el microshell es necesario definir en primer lugar su sintaxis. O
lo que es lo mismo, tener claro cual es el conjunto de reglas necesarias para escribir los
mandatos correctamente. La sintaxis de las lneas que deseamos sea capaz de interpretar
nuestro minishell personalizado es la siguiente:
<orden>::= cadena { argumento }
<lnea>::= orden [&]
Por tanto las reglas a cumplir son:
Cada lnea slo puede estar formada por una orden, la cual puede tener un
nmero variable de argumentos (las llaves {} indican que lo que est contenido
entre ellas, puede repetirse de 0 a n veces).

EUI-SG/INFOR.UVA.ES SO_PR02_20041012 2
Si al final de la lnea de rdenes se escribe el smbolo &, se entender que la
orden debe ejecutarse en segundo plano (los corchetes [] indican opcionalidad,
es decir, la repeticin 0 1 vez de lo que encierran).
Ejemplos vlidos que ha de ser capaz de interpretar nuestro minishell son las
siguientes lneas de rdenes:
$ ls -la
$ cat fichero1
$ ls la &
$ cat fichero1 &

defines.h

#define ... analizador.h/.c

int analizar (char *s);


funciones Consulta {
get_orden, num_argumentos,
get_argumentos, es_background}

msh.c

int main(...) {
...

ejecucion.h/.c

int ejecutar (parametros...);

Figura 3. Divisin modular propuesta para la realizacin de la prctica.


1.3. Descripcin modular del minishell a implementar
Para desarrollar cualquier aplicacin con cierta complejidad es til y conveniente
dividirla en mdulos, los cuales normalmente se organizan en ficheros fuente (.c) y
ficheros cabecera (.h) . Para la implementacin del minishell se propone la siguiente
divisin modular, que el alumno tiene que respetar. Esta divisin permite realizar la
prctica en varios sesiones de forma progresiva pudiendo probar cada uno de los
componentes por separado. El minishell est compuesto por tres mdulos ms un
fichero de definiciones comn para todos los mdulos:
defines.h: Fichero que contiene todas las definiciones comunes a los
mdulos que componen el minishell y que por tanto habr que especificar con
un include en la cabecera de cada uno de los ficheros que componen los mdulos
del minishell.
msh.c : Mdulo principal, contiene el main del programa y el bucle principal.
analizador.c y analizador.h: Ofrecen la interfaz necesaria para
analizar la lnea de comandos. Adems ofrece un conjunto de funciones para
consultar el comando analizado.
ejecucin.c y ejecucin.h: Ofrecen la interfaz necesaria para ejecutar
las ordenes usando los datos analizados.
La Figura 3 muestra grficamente tanto la divisin modular de la aplicacin con las
funciones principales como las dependencias existentes entre los distintos mdulos.
Para ver cual es la relacin entre los distintos mdulos, la Figura 4 muestra como se
procesara una lnea de rdenes. A grandes rasgos el funcionamiento es como sigue: se

EUI-SG/INFOR.UVA.ES SO_PR02_20041012 3
muestra el prompt al usuario y se lee una lnea de teclado (con getline()) y se
obtiene una cadena. Esta cadena se pasa a la funcin analizar() que analiza la lnea
y en el caso de que la sintaxis sea correcta se puede consultar el formato de la orden con
un conjunto de funciones que se proporcionan en el propio mdulo. Por ltimo se llama
a ejecutar() para ejecutar las orden correspondiente.

int main (...) {


...
while (TRUE) {
Leer Linea de teclado char *getline()
Analizar lnea int Analizar(char *linea)
Ejecutar int Ejecutar(...)
}
...
}

Figura 4. Bucle principal del minishell a desarrollar.


1.4 Breve descripcin de las funciones
Aunque en prxima sesiones se detallar con ms profundidad el funcionamiento y la
implementacin de cada funcin, a continuacin se describe brevemente las funciones
que contiene cada mdulo:
Funcin Descripcin
Mdulo analizador
void analizador_ini(void); Inicializa el analizador.
int analizar(char *s); Analiza una orden segn la sintaxis descrita. Retorna OK si
es sintcticamente correcto o ERROR si hay error.
char *get_orden(void); Devuelve la orden analizada en la funcin analizar.
int nun_argumentos(void); Devuelve el nmero de argumentos de la orden.
char **get_argumentos(void); Devuelve un vector de cadenas con los correspondientes
argumentos de la orden analizada.
int es_background(void); Indica si la orden analizada se ha lanzado en background
(&).
char *error_sintctico(void); Devuelve una descripcin del error sintctico detectado al
analizar.
Mdulo Ejecucin
int ejecutar ( Crea los procesos para ejecutar el mandato contenido en el
int nargs, parmetro orden. Parmetros de la funcin:
char *orden, nargs: nmero de argumentos de la orden.
char **args, orden: cadena con el nombre del mandato a
int bgnd); ejecutar.
args: vector de cadenas con los argumentos de la
orden.
bgnd: (TRUE o FALSE) indica si la instruccin se
ejecuta en modo background.
Retorna OK si ha ejecutado correctamente.

Tabla 1. Descripcin funcional de los mdulos a implementar.

EUI-SG/INFOR.UVA.ES SO_PR02_20041012 4
2. Bucle principal
2.1 Introduccin
En esta segunda seccin se va a desarrollar una primera implementacin del bucle
principal del shell (en el mdulo msh). Esta primera implementacin leer las rdenes
de teclado, las analizar y las imprimir por pantalla. Este bucle en sesiones posteriores
se ir completando para que se encargue tambin de realizar las acciones oportunas para
la ejecucin de las rdenes que se lean de teclado.
Para implementar este primer bucle principal, se deben tener en cuenta los siguientes
aspectos:
Lo primero que tiene que hacer el bucle principal es leer las rdenes a ejecutar,
es decir, ser capaz de leer desde teclado una lnea. Para ello crearemos una
funcin getline() en el mdulo msh. Esta funcin devolver una cadena de
caracteres con la lnea leda desde teclado.
Posteriormente, esta cadena ser procesada por la funcin analizar() del
mdulo analizador para comprobar si es una orden vlida y dividirla en los
distintos campos que la componen. Para poder acceder posteriormente a los
distintos campos de la orden, el mdulo analizador proporciona un conjunto de
funciones descritas en la Tabla 1.
Tambin se desea que este primer bucle saque el directorio actual como prompt.
Por otra parte, para poder finalizar la ejecucin de nuestro shell en un momento
dado, se pide que pueda finalizarse con la combinacin de teclas CTRL-D.
Por ltimo, para asegurarse de que el proceso de anlisis funciona correctamente
y familiarizarse con el manejo de las funciones del mdulo analizador se
propone crear una funcin que muestre por pantalla el resultado del anlisis
realizado. Esta funcin se llamar visualizar() y se implementar tambin
en el mdulo msh.
Entramos a continuacin en ms detalles, describiendo la estructura que tendr el bucle
principal y las dos funciones que se debern implementar en el mdulo msh.
2.2. Estructura del bucle principal
Bsicamente lo que tiene que hacer esta primera versin de nuestro shell es esperar a
leer desde teclado lneas correspondientes a rdenes a ejecutar, analizarlas para
comprobar que tienen una sintaxis adecuada y dividirlas en los distintos campos, para
posteriormente acceder fcilmente a estos campos por medio de las funciones que
proporciona el mdulo analizador, y finalmente visualizar el resultado de este anlisis.
Estos pasos los realizar de forma indefinida hasta que el usuario marque que desea
terminar la ejecucin por medio de la combinacin de teclas CTRL-D.
En este mdulo hay una funcin analizar() que recibe como parmetro un puntero
a carcter con la lnea leda desde teclado, y devuelve la constante OK o la constante
ERROR, ambas definidas en el mdulo defines.h. Esta funcin se encarga de
verificar la correccin sintctica de la lnea. En caso de que la sintaxis no sea correcta
analizar() muestra por pantalla un mensaje de error.
int analizar(char *s);
2.3. Funcin getline()
getline() ser la funcin a implementar para leer una lnea desde teclado:

EUI-SG/INFOR.UVA.ES SO_PR02_20041012 5
char * getline()
Devolver un puntero a carcter con la lnea leda desde teclado. Para su
implementacin se puede hacer uso de las funciones de lectura de carcter. La lnea
terminar cuando llegue un carcter \n. Adems en esta funcin tambin se habr de
comprobar que el tamao de la lnea no exceda el mximo definido en defines.h, en
caso de ocurrir esto, se mostrar un mensaje de error por pantalla.
Podemos hacer que sea sta la funcin encargada de mostrar el prompt en pantalla
mientras se espera leer una lnea. El prompt que se desea visualizar estar compuesto
por el directorio actual de trabajo, seguido de la constante PROMPT del mdulo
defines.h. Para obtener el directorio actual de trabajo se puede utilizar getcwd().
Adems, esta funcin deber detectar que desde teclado se ha pulsado la combinacin
de teclas CTRL-D (correspondiente al carcter final de fichero, EOF), para terminar la
ejecucin de nuestro shell. En caso de que se detecte el final de fichero, el shell debe
terminar despus de mostrar un mensaje por pantalla msh: logout.
2.4. Funcin visualizar()
La funcin visualizar() va a permitir mostrar el resultado del anlisis por pantalla.
void visualizar (void);
La funcin por cada una de las rdenes simples que compongan la orden leda, indicar
el nmero de argumentos que la forman y los mostrar. Adems indicar si la orden se
ejecuta en background.
En definitiva, esta funcin hace uso de las distintas funciones que permiten acceder a
los campos de la orden analizada y que estn definidas en el mdulo analizador.
2.5. Pruebas a realizar
Una vez realizados los pasos comentados en apartados anteriores, a continuacin se
propone realizar una serie de pruebas para verificar que el analizador funciona
correctamente y que todas las funciones del mdulo analizador devuelven la
informacin esperada.
Simplemente se tratara de leer rdenes simples y comprobar que nuestro shell nos
contesta correctamente indicando que hay una nica orden, el nmero de argumentos
que contiene y cuales son. Estas rdenes podran ser por ejemplo:
ls l
-i hola1 hola2
wc -l dkko/salida2
Despus, se propone realizar las pruebas anteriores de nuevo, pero lanzando las rdenes
en background, para comprobar que efectivamente el analizador es capaz de detectarlo.
Por ltimo se pretende comprobar que nuestro analizador es capaz de detectar errores
sintcticos en las rdenes tecleadas (en nuestro caso, que despus del smbolo & no haya
ninguna orden adicional).

EUI-SG/INFOR.UVA.ES SO_PR02_20041012 6
3. Mdulo de ejecucin
3.1 Introduccin
En esta sesin se va a desarrollar el mdulo de ejecucin, encargado de crear los
procesos que ejecutarn las diferentes rdenes que puedan aparecer en una determinada
lnea.
Como ya se ha explicado en las clases tericas, la creacin de un nuevo proceso en
UNIX siempre conlleva la utilizacin de ciertas llamadas al sistema. Esto podra
resumirse en la siguiente secuencia:
1. El proceso padre (en este caso el shell) realiza una llamada fork() para crear
un proceso hijo. Como resultado del fork(), tanto el padre como el hijo
estarn ejecutando el mismo programa, empezando ambos a partir de ese
instante con la instruccin que segua al fork(). La diferencia entre uno y otro
residir en que el sistema operativo devuelve distintos valores a cada proceso
como resultado de la llamada: el PID del proceso hijo es retornado al padre,
mientras que el hijo obtiene un cero como valor de retorno.
2. Si hay que realizar alguna redireccin de la entrada o salida estndar o de la
salida de error, sta tendr que ser efectuada por el proceso hijo antes de cambiar
el programa que est ejecutando. Esto es as porque el nombre de los ficheros a
utilizar en estas redirecciones, o el hecho de que se interconecte a este proceso
con otro mediante una tubera, puede saberse antes de efectuar el exec(), pues
el proceso sigue teniendo acceso a todas las variables de las que dispona el
padre (que fue el receptor de la lnea de entrada tecleada por el usuario), y all se
encuentra la informacin necesaria para efectuar tales cambios. En esta
implementacin de minishell no se considera la redireccin de los flujos
estndar de un proceso.
3. Una vez efectuadas las redirecciones, se procedera a cambiar el programa que
est ejecutando el proceso hijo (en caso de ser necesario), utilizando para ello la
llamada al sistema execvp() o cualquiera de sus variantes.
4. Por su parte, el proceso padre realizar la espera del proceso hijo mediante la
llamada al sistema wait() o waitpid(). La forma de realizar tal espera
depende de si el proceso hijo fue lanzado en segundo plano (con el operador &
al final de la orden) o no.
En este mdulo hay que realizar estos pasos (salvo el de la redireccin de los flujos
estndar) de manera apropiada. Para ello contamos con la ayuda de las funciones ya
implantadas hasta ahora, mediante las cuales se puede acceder a toda la informacin
necesaria para llevar a cabo las tareas ms importantes de esta sesin.
A continuacin se detalla la cabecera que tendrn las funciones a implementar en este
mdulo, as como los problemas o alternativas que encontraremos al disear tales
funciones.
3.2. Estructura del mdulo de ejecucin
En este mdulo deber implantarse la siguiente funcin, en un fichero que deber
llamarse ejecucion.c:
int ejecutar (int nargs, char *orden, char **args,
int bgnd)
Esta nica funcin requiere cuatro parmetros de entrada:

EUI-SG/INFOR.UVA.ES SO_PR02_20041012 7
nargs, informa del nmero de argumentos de la orden.
orden, es una cadena que contiene el nombre de la orden a ejecutar.
args, es un vector de cadenas con los argumentos de cada orden, es decir, en la
posicin (i-1) del vector se encuentra el i-simo argumento de la orden a
ejecutar.
bgnd, es un entero que indica si el proceso debe ejecutarse en background
(TRUE) o no (FALSE).
A su vez, el valor retornado por esta funcin ejecutar ser OK o ERROR, en funcin de si
la lnea ha podido ejecutarse sin problemas o de si se ha encontrado un error en alguno
de los pasos necesarios para ello, respectivamente.
3.3. rdenes en segundo plano
Otro problema que deber resolverse adecuadamente es la gestin de la terminacin de
las lneas de rdenes. Como ya hemos mencionado anteriormente, la lnea no debe darse
por concluida hasta que no haya terminado el ltimo de los procesos que aparezcan en
ella. Adems, tambin debe tenerse en cuenta que las rdenes podrn ser lanzadas en
segundo plano, mediante el operador correspondiente ("&").
Como resultado de todo esto, cuando una lnea de rdenes sea lanzada en "primer
plano" habr que ir esperando a que los procesos hijos vayan terminando, hasta que lo
haga el que apareca como ltima orden de la lnea. Sin embargo, cuando la lnea se
lance en "segundo plano", el shell no tiene por qu esperar a que termine ninguno de los
procesos creados. Es decir, ya puede presentar el prompt y leer la siguiente orden de
inmediato.
No obstante, no se recomienda la utilizacin exclusiva de la llamada waitpid()
empleando como primer argumento el PID del nico proceso que deba esperarse para
las rdenes en primer plano, ya que esto conllevara la generacin de mltiples procesos
zombies (uno por cada proceso que haya terminado y que el shell no haya decidido
esperar). Para evitarlo, trate de disear algn mecanismo de espera que garantice que el
shell "vea" la terminacin de todos sus procesos hijos, aunque tal terminacin se
produzca mucho antes de que el shell se interese por ella.
La solucin ms elegante sera gestionar a las lneas ejecutadas en segundo plano de una
forma similar a la empleada por el bash o el ksh. En estos intrpretes, cuando se ha
detectado que la orden en segundo plano ha terminado, se muestra por pantalla una lnea
informando del tipo de terminacin que ha tenido la orden (si es normal, se muestra la
palabra "Done" por pantalla; si ha sido terminada con una seal, se muestra la palabra
"Killed"; si ha terminado con error, aparecer la palabra "Exit" seguida por el
cdigo de error devuelto por el programa, ...), y a continuacin se escribe tambin la
lnea de rdenes que haya producido tales resultados. Esta solucin se considerar una
ampliacin y, en caso de realizarla, mejorara la calificacin obtenida.
En cualquier caso, lo que se exigir como mnimo ser una gestin que no produzca
como resultado procesos zombies a partir de las rdenes lanzadas en segundo plano.

EUI-SG/INFOR.UVA.ES SO_PR02_20041012 8
4. Tratamiento de seales
4.1. Introduccin
El tratamiento de seales en los intrpretes de rdenes UNIX tradicionales ha dependido
en gran medida del tipo de gestin de procesos que stos soportaban. Los intrpretes
ms complejos proporcionaban soporte para la gestin de grupos de procesos y
utilizaban stos para modelar el concepto de trabajo y permitir la parada, el cambio de
primer a segundo plano, o de segundo a primer plano de estos trabajos. En estos casos
se precisaba gestionar algunas seales adicionales que tenan cierta influencia en la
gestin de los trabajos, as como la creacin de los grupos de procesos necesarios para
soportarlos. Por ejemplo, el intrprete bash ignora por omisin las seales SIGTERM,
SIGQUIT y SIGINT (esta ltima no es realmente ignorada, sino que tiene un
manejador asociado para que la orden interna wait sea interrumpible). Cuando su
control de trabajos est habilitado, tambin pasa a ignorar las seales SIGTTIN,
SIGTTOU y SIGTSTP. Para todos los procesos lanzados en primer plano, estas seales
no estarn ignoradas, pero para los lanzados en segundo plano, SIGINT y SIGQUIT s
que son ignoradas si el control de trabajos est inhabilitado. Adems de esto, el
tratamiento por omisin realizado por el intrprete puede modificarse mediante la orden
interna trap, al menos en lo que hace referencia al tratamiento de las seales dirigidas
al propio intrprete. Como puede verse, bash no utiliza una gestin sencilla.
El estndar POSIX no requiere que cualquier intrprete implemente esta gestin
avanzada, por lo que nicamente exige un tratamiento de las seales dirigido a evitar
que el propio intrprete pueda ser eliminado al utilizar ciertas combinaciones de teclas.
En esta sesin deber ampliarse el mdulo de ejecucin, as como el subprograma
principal del intrprete para dar soporte a este tratamiento de seales. Para ello habr
que utilizar debidamente la llamada al sistema sigaction(), con la que se podr
modificar la gestin de seales que llevar a cabo el shell o los procesos que ste
genere, dependiendo de dnde se use.
4.2. Gestin de seales
En nuestro intrprete de rdenes no vamos a realizar ningn tipo de gestin de trabajos,
por lo que la gestin de las seales ser sencilla. Los requerimientos para sta se
centrarn en:
El intrprete deber ignorar cualquiera de las siguientes seales:
o SIGINT, o seal de interrupcin de teclado. Se puede generar
normalmente mediante la combinacin de teclas [Ctrl]+[C]. Su
tratamiento por omisin es terminar al proceso que la reciba. En los
intrpretes con gestin de trabajos, esta seal slo se dirige al grupo de
procesos en primer plano, pues los generados en segundo plano utilizan
otros grupos de procesos que no tienen terminal asociada y que, por
tanto, no pueden recibir ninguna seal generada desde teclado. En
nuestro intrprete no vamos a preocuparnos por la gestin de trabajos.
o SIGQUIT, o seal de terminacin por teclado. Se genera con la
combinacin de teclas [Ctrl]+[\] (aunque tanto la combinacin para
sta como para la anterior seal pueden modificarse con la orden stty.
De hecho, la combinacin en uso puede consultarse con un stty
a). Su tratamiento por omisin es terminar al proceso que la reciba,

EUI-SG/INFOR.UVA.ES SO_PR02_20041012 9
realizando adems un volcado de memoria en un fichero (al que se le
suele dar como nombre core). Al igual que en el caso anterior, esta
seal nicamente podr ser entregada a los procesos que tengan acceso a
la terminal donde se haya pulsado la combinacin de teclas
correspondiente.
o SIGTTIN. Esta seal es enviada por el sistema operativo cuando un
proceso sin acceso a la terminal intenta efectuar una lectura de teclado.
Como ya hemos comentado anteriormente, los procesos en segundo
plano no deberan tener acceso a la terminal. Por tanto, lo que tratamos
de evitar al ignorar esta seal es que nuestro intrprete quede parado (ya
que pararse es el tratamiento por omisin para esta seal) cuando sea
lanzado desde la lnea de rdenes en segundo plano.
o SIGTTOU. Esta seal es muy similar al anterior, pero relacionada con la
salida de la terminal (es decir, con el acceso a la pantalla) en lugar de la
entrada.
Por su parte, los procesos lanzados en segundo plano slo tendrn que ignorar
las seales SIGINT y SIGQUIT. Esto es as porque no vamos a realizar
ninguna gestin de sesiones ni grupos de procesos y, en nuestro intrprete de
rdenes, siempre tendremos a todos los procesos asociados con la terminal. En
un intrprete ms avanzado (cualquiera de los intrpretes estndares de UNIX:
ksh, csh o bash, por ejemplo), al realizar gestin de grupos, los procesos en
segundo plano no estaran asociados a la terminal y jams podran recibir tales
seales. Por otra parte, nuestra gestin simplificada tendr la ventaja de que los
procesos en segundo plano que se generen con nuestro shell jams podrn
recibir las seales SIGTTIN ni SIGTTOU, por lo que no merecer la pena
realizar ningn tratamiento para ellas. No obstante, hay que tener especial
cuidado con la entrada de los procesos en segundo plano. En el mdulo de
redireccin habr tenido que comprobarse que la entrada de estas rdenes est
redirigida y, si no lo estaba, efectuar una redireccin utilizando el fichero
/dev/null con lo que la orden en segundo plano leera de inmediato un fin
de fichero. Si no se hizo as, nos encontraremos con el problema de tener a
varios procesos compitiendo por la entrada que quiera facilitar el usuario, con
resultados bastante caticos.
Por ltimo, los procesos en primer plano deberan tener el tratamiento por
omisin para todas las seales. Por tanto, habr que recuperar tal tratamiento
utilizando las llamadas al sistema apropiadas, pues estos procesos habrn
heredado la gestin realizada por nuestro intrprete.
As pues se debe aadir el cdigo necesario para implantar esta gestin dentro de los
mdulos propuestos. Para ello habr que modificar el fichero msh.c para tener en l la
gestin relacionada con el propio intrprete y tras esto, modificar tambin el fichero
ejecucion.c, donde se incluir la gestin tanto para los procesos en primer plano
como para los procesos en segundo plano.
Todas estas modificaciones tendrn que utilizar las llamadas y estructuras de datos
relacionadas con seales. Para ello es conveniente repasar la documentacin existente
sobre la llamada al sistema sigaction() (tanto los apuntes de clase como las
pginas de manual).

EUI-SG/INFOR.UVA.ES SO_PR02_20041012 10

You might also like