SISTEMAS OPERATIVOS II
Tercer curso Ingeniería Informática. Curso 2005-2006
Práctica 1: Procesos en UNIX.
Comenzar la codificación de un intérprete de comandos (shell) en UNIX, que se irá
completando en suscesivas prácticas. Dicho intérprete incluirá de momento los comandos que
se citan a continuación. Los argumentos entre corchetes [] son opcionales. Los argumentos
separados por | indican que debe ir uno u otro, pero no ambos simultaneamente. No debe
dilapidar memoria (ejemplo: variable que se asigna cada vez que se llama a una función y no se
libera). Cuando el shell no pueda ejecutar una acción por algún motivo, debe indicarlo con un
mensaje como el que se obtiene con sys_errlist[errno] o con perror() (por ejemplo,
si no puede cambiar de directorio debe indicar por qué). En ningún caso debe producir un error
de ejecución. Las direcciones de memoria deben mostrase en hexadecimal. La
información que se nuestra en pantalla no debe incluir en ningun caso líneas en blanco. El
shell leerá de su entrada estándar y escribirá en su salida estándar, de manera que
podría ser ejecutado un archivo de comandos invocando el shell con su entrada estándar
redireccionada a dicho archivo.
- autores
- Indica los nombres y los logins de los autores de la práctica.
- fin
- Termina la ejecución del intérprete de comandos.
- exit
- Termina la ejecución del intérprete de comandos.
- chdir [dir]
- Cambia el directorio actual a dir. Si no se le suministra
argumento informa del directorio actual.
- prompt prompt
- Cambia el indicador (prompt) del intérprete de comandos.
- ruta [-a|-d|-n|-p] [dir]
- Manipula la ruta de búsqueda del intérprete
de comandos.
La ruta de búsqueda del intérprete de comandos es el conjunto de directorios donde el shell
busca los ejecutables (Su misión es análoga a la variable de entorno PATH en el
shell del sistema). NO DEBE implementarse con una variable de entorno. Los directorios se
especificarán sin el caracter '/' al final Ejemplos
#ruta -a /usr/local/bin /* correctos */
#ruta -a /
#ruta -a .
......
#ruta -a /usr/local/bin/ /*incorrecto*/
#ruta -a ./ /*incorrecto*/
- ruta -a dir
- Añade dir a la ruta de búsqueda.
- ruta -d dir
- Elimina dir de la ruta de búsqueda.
- ruta -n
- Vacía la ruta de búsqueda.
- ruta -p
- Añade los directorios de la variable de entorno PATH a la ruta de búsqueda.
- ruta dir
- Indica si dir está en la ruta de búsqueda.
- ruta
- Muestra la ruta de búsqueda.
- cual ejecutable
- Busca ejecutable en la lista de directorios que constituyen la ruta de búsqueda del intérprete de
comandos y devuelve la trayectoria completa hasta él (análogo al comando which del sistema).
Si no lo encuentra lo indicará. Si se le indica una trayectoria completa (empezando por ., por /
o por ..) indicará si dicho fichero existe o no
#ruta -a /usr/openwin/bin
#cual xterm
/usr/openwin/bin/xterm
#cual xternp
xternp: no encontrado
#cual ./aa.out
./aa.out: no encontrado
#cual ./a.out
./a.out
- getpid
- Devuelve el pid del proceso y de su proceso padre.
- fork
- El intérprete de comandos crea un hijo con fork() y se queda (el propio intérprete
de comandos) en espera hasta que dicho hijo (el creado con fork) termine. El hijo inicializa su lista de procesos en
segundo plano a vacía.
- exec com
- El intérprete de comandos ejecuta, sin crear un nuevo proceso
(reemplaza su código), el programa especificado en com. com representa un
ejecutable con sus parámetros. Para poder ser ejecutado, dicho ejecutable debe residir en uno
de los directorios de la ruta de búsqueda del intérprete de comandos (ruta)o bien
especificarse la trayectoria completa hasta él (comenzando por /, . o ..). Debe usarse la
llamada al sistema execv.
Ejemplo
#exec /usr/bin/ls -l /home /*ejecuta /usr/bin/ls*/
....
#exec ./a.out -l /*ejecuta a.out,
/*que esta en el directorio actual */
......
#exec ls -l /* para ejecutar esto, es necesario */
/*que el directorio /usr/bin, */
/*donde esta el programa ls, se haya incluido */
/* a la ruta de busqueda */
- comando
- Totalmente análogo al comando exec, salvo que el shell crea el proceso
que ejecuta dicho comando y espera a que termine (la ejecución es, por tanto, en primer plano).
Todo lo dicho sobre los ejecutables en el comado exec es aplicable aquí .
Ejemplo
#/usr/bin/ls -l /home /*crea un proceso que ejecuta /usr/bin/ls*/
....
#./a.out -l /* crea un proceso que ejecuta a.out,*/
...... /* que esta en el directorio actual */
#ls -l /* para ejecutar esto, es necesario que el directorio */
/* /usr/bin, donde esta el programa ls, se haya incluido */
/* a la ruta de busqueda */
.
- com &
- Análogo a com pero la ejecución es en segundo plano (el shell no
espera a que el proceso termine).. Afecta a tanto a comando como a LV comando.
Ejemplos
#xterm -e csh &
crea un proceso que ejecuta xterm en segundo plano.
- procs [-n|-s|-a]
- Muestra una lista de los procesos que ha mandado este shell
en segundo plano. (dicha lista es mantenida por el propio shell). Para cada proceso debe
indicar, la línea de comando con que fue lanzado, la hora a la que se inició, y el estado
(activo, terminación normal, terminación debido a una seņal), asi como el valor
devuelto (o la señal en caso de parado o terminado debido a una señal). El listado debe
imprimir SOLO UNA LINEA POR CADA PROCESO. Las opciones -n, -s y -a se utilizan para eliminar de
la lista los procesos que ya hayan terminado: la opción -n elimina de la lista los procesos que
hayan terminado normalmente, la opción -s los que hayan terminado debido a una señal y la
opción -a todos los que hayan terminado.
- recursiva [-a|-n|-d] n
- Invoca a la función recursiva n veces, la opción
-a, -n o -d indica si la memoria asignada con malloc en dicha función debe liberarse (a)ntes de
la siguiente llamada recursiva, (d)espués o (n)o liberarse. Si no se indica una opción se
supone que la memoria se libera despues de la llamada (-d). La función recursiva recibe dos
parámetros: uno que indica el número de veces que se tiene que invocar y otro que indica cuando liberar la
memoria asignada con malloc; tiene 3 variables, un array automatico de 512 caracteres, un array
estático de 512 caracteres y un puntero a caracter.
Esta función debe hacer lo siguiente
- asignar memoria (mediante malloc) al puntero para 512 caracteres.
- imprimir
- el valor y la dirección del parámetro que recibe.
- el valor y la dirección del puntero.
- la dirección de los dos arrays (el nombre del array como puntero).
- si se ha especificado la opción -a liberar la memoria asignada al puntero.
- invocarse a si misma con (n-1) como parámetro (si n>0).
- si se ha especificado la opción -d liberar la memoria asignada al puntero.
Un posible código pra la función recursiva (sin las definiciones de constantes)podría ser:
void recursiva (int n, int liberar)
{
char automatico[TAMANO];
static char estatico[TAMANO];
void * puntero;
puntero=(void *) malloc (TAMANO);
printf ("parametro n:%d en %p\n",n,&n);
printf ("valor puntero:%p en direccion: %p\n", puntero,&puntero);
printf ("array estatico en:%p, array automatico en %p\n", estatico,automatico);
if (liberar==ANTES)
free (puntero);
if (n>0)
recursiva(n-1,liberar);
if (liberar==DESPUES)
free (puntero);
}
- direcciones [-f|-v]
- Imprime las nombres y las direcciones de las funciones que
implementan los comandos del shell (-f), de las variables globales (-v). Si no se especifica ni -f
ni -v imprime las direcciones de las funciones y de las variables globales.
Información detallada de las llamadas al sistema y las funciones de la librería
debe obternerse con man (exec, chdir, fork, strtok, waitpid, getpid..)
FORMA DE ENTREGA
Va a ser utilizado el servicio de recogida de prácticas suministrado por el Centro de Cálculo de esta Facultad y parte del proceso de corrección
de las prácticas va a ser automtico (compilación, listado de practicas entregadas etc) por lo cual deben entregarse exactamente como se indica a continuación:
FECHA DE ENTREGA VIERNES 21 ABRIL 2006