Sie sind auf Seite 1von 7

Prctica 6: Terminacin de Procesos. Ejecucin de Programas.

Pgina 1

Prctica 6. Terminacin de Procesos (exit y wait).


Ejecucin de Programas (exec).
1. Objetivos.

Utilizar llamadas al sistema Linux para terminar procesos y para conocer el estado en
el que finalizan otros procesos.

Ejecutar programas diferentes desde un programa escrito en lenguaje C.

2. Terminacin de Procesos: exit y wait.


Un caso tpico de programacin tiene lugar cuando un proceso permanece a la espera de
que termine otro proceso hijo suyo antes de continuar ejecutndose.
Un ejemplo de esta situacin se tiene cuando se escribe una orden en la lnea de comandos y
se pulsa [intro]: el proceso shell crea un proceso hijo suyo que se encarga de ejecutar la orden
solicitada y no muestra el cursor (seal de espera por una nueva orden) hasta que no se ha
ejecutado completamente. Como es lgico, esto no ocurre as cuando la orden se ejecuta en
background.
Para poder sincronizar los procesos padre e hijo, se emplean las llamadas exit y wait, cuyas
declaraciones son las siguientes:
#include <stdlib.h>

#include <sys/types.h>

void exit (int estado);

#include <sys/wait.h>
pid_t wait(int *estado);

exit termina la ejecucin de un proceso y devuelve al sistema el valor estado. Si el proceso


padre del que ejecuta la llamada a exit est ejecutando una llamada a wait, se le notifica la
terminacin de su proceso hijo y se le envan los ocho bits menos significativos de estado. Con
esta informacin, el proceso padre puede saber en qu condiciones ha terminado el proceso
hijo.
wait suspende la ejecucin del proceso que la invoca hasta que alguno de sus procesos hijo
finaliza. La forma de invocar a wait es:
pid_t pid;
int estado,edad;
pid=wait(&estado);

Prctica 6: Terminacin de Procesos. Ejecucin de Programas.

Pgina 2

Se obtiene en pid el valor del identificador de proceso de alguno de los hijos zombies (un
proceso zombie es el que acaba de finalizar). En la variable estado se almacena el valor que el
proceso hijo le enva al padre mediante la llamada a exit y que da idea de la condicin de
finalizacin del proceso hijo. Si se quiere ignorar este valor, se puede pasar como parmetro
un puntero NULL (pid=wait(NULL)).
En el archivo de cabecera <sys/wait.h> se definen diferentes macros que permiten analizar
el valor de estado para determinar la causa de terminacin del proceso. En particular, el
proceso padre puede obtener el valor de los ocho bits menos significativos del parmetro que
recibe

desde

la

llamada

exit

por

parte

del

hijo

utilizando

la

macro

WEXITSTATUS(estado).
Si durante la llamada a wait se produce algn error, la funcin devuelve 1 y en errno
quedar el cdigo del tipo de error producido.
Como es lgico, si el proceso que invoca a wait no tiene ningn proceso hijo vivo, se produce
un error.
Por ejemplo, sea el siguiente cdigo correspondiente a un proceso cuyo pid es igual a 10 y
que tiene un hijo con pid igual a 20:
#include <sys/types.h>
#include <sys/wait.h>
#include <stdlib.h>
...
int main (void){
pid_t pid;
int estado,edad,edadHijo;
...
pid=wait(&estado);
edad=WEXITSTATUS(estado);
printf("Mi hijo %d ha fallecido a los %d aos.\n",pid,edad);
pid=wait(&estado);
printf("pid=%d\n",pid);
...
}

Prctica 6: Terminacin de Procesos. Ejecucin de Programas.

Pgina 3

Si el cdigo del proceso hijo termina con las siguientes instrucciones:


...
edadHijo=140;
exit(edadHijo);
}
Cuando el proceso padre llega a la instruccin wait suspende su ejecucin y permanece a la
espera de que finalice el proceso hijo. ste finaliza cuando alcanza la instruccin exit que
tiene como parmetro la variable edadHijo, cuyo valor es 140 en el proceso hijo.
Es ahora cuando el proceso padre se desbloquea y la instruccin wait devuelve como
resultado el valor del pid del proceso hijo que ha terminado (en este caso, el valor 20) y lo
almacena en la variable pid.
En los ocho bits menos significativos de la variable estado queda almacenado el valor de los
ocho bits menos significativos de la variable edadHijo (parmetro de la instruccin exit del
proceso hijo). Como es posible que el resto de bits de la variable estado tengan valores no
deseados, se utiliza la macro WEXITSTATUS para obtener el valor correcto del parmetro
enviado por el proceso hijo.
As, tras finalizar el proceso hijo, el proceso padre mostrara en pantalla el siguiente mensaje:
Mi hijo 20 ha fallecido a los 140 aos.
Posteriormente, el padre pretende esperar a que termine otro proceso hijo (wait). Puesto que
ya no hay ningn hijo vivo, la llamada a wait produce un error y devuelve el valor 1.
Entonces se vuelca en pantalla el mensaje:
pid=-1

3. Ejecucin de programas: exec.


Existe toda una familia de funciones exec tiles para lanzar programas ejecutables desde un
programa escrito en lenguaje C. Dentro de esta familia cada funcin tiene su sintaxis pero
todas tienen aspectos comunes y obedecen al mismo tipo de funcionamiento: se carga un
programa en la zona de memoria del proceso que ejecuta la llamada sobreescribiendo los
segmentos del programa antiguo con los del nuevo. Es decir, el programa viejo es
SUSTITUIDO por el nuevo y NUNCA se volver a l para proseguir su ejecucin, pues es
el programa nuevo el que pasa a ejecutarse.

Prctica 6: Terminacin de Procesos. Ejecucin de Programas.

Pgina 4

La declaracin de la familia de funciones exec es la siguiente:


int execl (char *ruta, char *arg0, char * arg1,..., char *argn, (char *)0);
int execv (char *ruta, char *argv[]);
int execle (char *ruta, char *arg0, char * arg1,..., char *argn, (char *)0, char
*envp[]);
int execve (char *ruta, char *argv[], char *envp[]);
int execlp (char *fichero, char *arg0, char * arg1,..., char *argn, (char *)0);
int execvp (char *fichero, char *argv[]);

Donde:
ruta es una cadena con el path (absoluto o relativo) de un archivo ejecutable.
fichero es el nombre de un fichero ejecutable.
arg0, arg1,..., argn son cadenas de caracteres que constituyen la lista de parmetros que se le
pasa al nuevo programa. Por convenio, al menos arg0 est presente siempre y coincide con
ruta o con el ltimo componente de ruta. Hay que destacar que tras argn se pasa un puntero
NULL para indicar el final de los argumentos.
argv es un array de cadenas de caracteres que constituye la lista de argumentos que va a
recibir el nuevo programa. Por convenio, argv debe tener al menos un elemento, que coincide
con ruta o con el ltimo componente de ruta. El final de argv se indica colocando un puntero
NULL detrs del ltimo parmetro.
envp es un array de punteros a cadenas de caracteres que constituyen el entorno en el que se
va a ejecutar el nuevo programa. envp tambin termina con un puntero NULL.
Un programa escrito en C recibe estos parmetros a travs de la funcin main, que se puede
declarar de la siguiente forma:
void main (int argc, char *argv[], char *envp[]);
As, por ejemplo, se podra obtener un listado completo de los archivos del directorio actual
cuyo nombre termine con la cadena .c utilizando la instuccin execl:
execl("/bin/ls","ls","-l","*.c", (char *)0);
La instruccin anterior ejecuta la orden ls de igual manera que si se escribiera en la lnea de
comandos la siguiente orden:
ls l *.c

Prctica 6: Terminacin de Procesos. Ejecucin de Programas.

Pgina 5

Si hubiera ms instrucciones posteriores a execl no se ejecutaran porque el programa ls


sustituye al que lo llama.
En el caso de que se deseara ejecutar ms instrucciones, sera necesario crear un proceso hijo
que se encargara de llamar a la orden execl mientras el padre podra continuar realizando
otras tareas.

Prctica 6: Terminacin de Procesos. Ejecucin de Programas.

Pgina 6

4. Enunciado de la prctica.
Escribir un programa en lenguaje C que reciba un parmetro desde la lnea de rdenes y se
encargue de:
-

Comprobar que la sintaxis empleada ha sido adecuada y, en caso contrario,


mostrar por pantalla cul es la correcta:
La sintaxis correcta es:

dormilones nmero_hijos

Crear un nmero de procesos hijo dado por el parmetro de la lnea de rdenes.

Cada uno de los procesos hijo generar un nmero aleatorio entre 1 y 10,
mostrar un mensaje indicando su pid y el tiempo que va a dormir. A
continuacin dormir ese nmero de segundos. Una vez transcurrido este
tiempo, el proceso hijo termina con una llamada a exit tal que el proceso padre
pueda conocer el tiempo que dicho hijo ha estado durmiendo.

El proceso padre, por su parte, esperar (wait) a que terminen todos sus procesos
hijo. A medida que vayan finalizando ir mostrando el valor del pid de cada hijo
junto con el tiempo que ha dormido.

Cuando todos los hijos hayan terminado, el proceso padre debe dormir durante 2
segundos y, posteriormente, ejecutar ( execl ) el siguiente programa: ps lc.

Por qu no se visualiza ningn mensaje si se coloca despes de la orden execl la instruccin


siguiente?
printf("PADRE: ejecucin terminada\n");
Generacin de nmeros aleatorios en lenguaje C.
Para generar nmeros aleatorios, el lenguaje C dispone de las funciones srand y rand, que
aparecen en el archivo de cabecera stdlib.h.
void srand (unsigned semilla);
Inicializa el generador de nmeros aleatorios. La secuencia generada depende del
valor de semilla y es siempre la misma para la misma semilla.

Prctica 6: Terminacin de Procesos. Ejecucin de Programas.

Pgina 7

int rand (void);


Permite obtener un nmero aleatorio.
Para generar un entero aleatorio entre 1 y 10 se puede utilizar el siguiente cdigo dentro de
cada proceso hijo:
srand(getpid());
tiempo=1+(int)(10.0*rand()/(RAND_MAX+1.0));

Nota: Normalmente, el generador de nmeros aleatorios se inicializa con el


valor del reloj del sistema para evitar que se repita la misma secuencia cada
vez que se ejecuta el programa.

Das könnte Ihnen auch gefallen