wait, waitpid y waitid, gestión de múltiples procesos
18 03 2008
Tras ver como se pueden generar varios procesos empleando fork ahora veremos como podemos controlar sus tiempos de ejecución con wait, waitpid y waitid.
Esta es la firma de las dos primeras funciones:
pid_t wait(int *status)
pid_t waitpid(pid_t pid, int *status, int options)
Estas funciones se utilizan para esperar hasta que un proceso cambie de estado. Se emplean como ya hemos comentado para esperar por un cambio de estado en un proceso hijo del proceso que realiza la llamada ha estas funciones. Un cambio de estado para el proceso hijo puede ser uno de estos 3: el hijo ha muerto, el hijo ha sido detenido por una señal o el hijo continua su ejecución tras recibir una señal apropiada (resume).
Si el hijo ha cambiado de estado antes de la ejecución del wait entonces la llamada a esta función retornará inmediatamente. En caso contrario la llamada bloqueará el proceso hasta que se produzca este cambio de estado.
wait() espera hasta que uno cualquiera de los hijos del proceso que realiza la llamada a wait cambie de estado. waitpid en su lugar suspende la ejecución del proceso actual hasta que el hijo, especificado por el argumento pid cambie su estado. Por defecto, waitpid espera sólo por la muerte de los hijos, pero este comportamiento es modificable mediante el parámetro options.
El valor de pid puede tomar estos valores
Más pequeño que -1 hace que se espere por cualquier hijo cuyo id de proceso de grupo sea igual al valor absoluto de este argumento. Igual a -1 esperará por cualquier hijo, el primero en cambiar de estado (igual comportamiento que wait), cero indica que se esperará por cualquier proceso hijo que tenga el mismo id de grupo de procesos y mayor que cero hará que se espere por el hijo cuyo pid coincida con este valor.
El parámetro optiones es una máscara OR de diversos constantes, sólo las enumeraré pero es sencillo encontrar información sobre ellas utilizando el comando man: WHOHANG, WUNTRACED, WCONTINUED, WIFEXITED, WEXITSTATUS, WIFSIGNALED, WTERMSIG, WCOREDUMP, WIFSTOPPED, WSTOPSIG y WIFCONFIRMED
Existe además otra función llamada waitid que realiza una función análoga a las anteriores pero proporciona un mayor control sobre que cambios de estado en el hijo deben ser esperados. La firma de la función es la siguiente
int waitid(idtype_t idtype, id_t id, siginfo_t *infop, int options)
Los archivos de cabecera donde se definen estas 3 funciones y las constantes y tipos necesarios para su utilización están en los archivos de cabecera sys/types.h y sys/wait.h
Los parámetros id e idtype seleccionan a que hijo(s) se debe esperar, options tiene el mismo significado que en el caso de waitpid().
En cuanto a los los parámetros que retornas estas tres funciones wait() en caso de éxito devuelve el pid del proceso hijo que ha cambiado de estado. En caso de error devuelve -1. waitpid() en caso de éxito devuelve lo mismo que wait() y en caso de error -1 pero si se ha especificado la constante WHOHANG la función no bloquea y devuelve cero si no hay ningún hijo que haya cambiado de estado. Por último waitid() devuelve cero en caso de éxito o si WHOHANG ha sido activado y no hay hijo que haya cambiado de estado y -1 en caso de error.
Volviendo a nuestro programa fork vamos ha hacerle unas modificaciones para que el padre espere a la muerte de sus 2 hijos:
waitpid hace que se espere hasta que terminen los dos hijos identificados en el programa por pid1 y pid2
Para compilar y ejecutar este programa copia el fragmento de código en un fichero llamado forks.c y después en el mismo directorio donde lo has grabado ejecuta las siguientes líneas
$ gcc forks.c
$ ./a.out
Recuerda que para ver la pid de la shell donde ejecutas el programa debes ejecutar:
$ echo $$
Comentarios :
No hay comentarios »
Esta es la firma de las dos primeras funciones:
pid_t wait(int *status)
pid_t waitpid(pid_t pid, int *status, int options)
Estas funciones se utilizan para esperar hasta que un proceso cambie de estado. Se emplean como ya hemos comentado para esperar por un cambio de estado en un proceso hijo del proceso que realiza la llamada ha estas funciones. Un cambio de estado para el proceso hijo puede ser uno de estos 3: el hijo ha muerto, el hijo ha sido detenido por una señal o el hijo continua su ejecución tras recibir una señal apropiada (resume).
Si el hijo ha cambiado de estado antes de la ejecución del wait entonces la llamada a esta función retornará inmediatamente. En caso contrario la llamada bloqueará el proceso hasta que se produzca este cambio de estado.
wait() espera hasta que uno cualquiera de los hijos del proceso que realiza la llamada a wait cambie de estado. waitpid en su lugar suspende la ejecución del proceso actual hasta que el hijo, especificado por el argumento pid cambie su estado. Por defecto, waitpid espera sólo por la muerte de los hijos, pero este comportamiento es modificable mediante el parámetro options.
El valor de pid puede tomar estos valores
Más pequeño que -1 hace que se espere por cualquier hijo cuyo id de proceso de grupo sea igual al valor absoluto de este argumento. Igual a -1 esperará por cualquier hijo, el primero en cambiar de estado (igual comportamiento que wait), cero indica que se esperará por cualquier proceso hijo que tenga el mismo id de grupo de procesos y mayor que cero hará que se espere por el hijo cuyo pid coincida con este valor.
El parámetro optiones es una máscara OR de diversos constantes, sólo las enumeraré pero es sencillo encontrar información sobre ellas utilizando el comando man: WHOHANG, WUNTRACED, WCONTINUED, WIFEXITED, WEXITSTATUS, WIFSIGNALED, WTERMSIG, WCOREDUMP, WIFSTOPPED, WSTOPSIG y WIFCONFIRMED
Existe además otra función llamada waitid que realiza una función análoga a las anteriores pero proporciona un mayor control sobre que cambios de estado en el hijo deben ser esperados. La firma de la función es la siguiente
int waitid(idtype_t idtype, id_t id, siginfo_t *infop, int options)
Los archivos de cabecera donde se definen estas 3 funciones y las constantes y tipos necesarios para su utilización están en los archivos de cabecera sys/types.h y sys/wait.h
Los parámetros id e idtype seleccionan a que hijo(s) se debe esperar, options tiene el mismo significado que en el caso de waitpid().
En cuanto a los los parámetros que retornas estas tres funciones wait() en caso de éxito devuelve el pid del proceso hijo que ha cambiado de estado. En caso de error devuelve -1. waitpid() en caso de éxito devuelve lo mismo que wait() y en caso de error -1 pero si se ha especificado la constante WHOHANG la función no bloquea y devuelve cero si no hay ningún hijo que haya cambiado de estado. Por último waitid() devuelve cero en caso de éxito o si WHOHANG ha sido activado y no hay hijo que haya cambiado de estado y -1 en caso de error.
Volviendo a nuestro programa fork vamos ha hacerle unas modificaciones para que el padre espere a la muerte de sus 2 hijos:
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
int main(int argc, char *argv[])
{
pid_t pid1, pid2;
int status1, status2;
if ( (pid1=fork()) == 0 )
{ /* hijo */
printf("Hijo 1 (%d, hijo de %d)\n", getpid(), getppid());
}
else
{ /* padre */
if ( (pid2=fork()) == 0 )
{ /* segundo hijo */
printf("Hijo 2 (%d, hijo de %d)\n", getpid(), getppid());
}
else
{ /* padre */
/* Esperamos al primer hijo */
waitpid(pid1, &status1, 0);
/* Esperamos al segundo hijo */
waitpid(pid2, &status2, 0);
printf("Padre (%d, hijo de %d)\n", getpid(), getppid());
}
}
return 0;
}
waitpid hace que se espere hasta que terminen los dos hijos identificados en el programa por pid1 y pid2
Para compilar y ejecutar este programa copia el fragmento de código en un fichero llamado forks.c y después en el mismo directorio donde lo has grabado ejecuta las siguientes líneas
$ gcc forks.c
$ ./a.out
Recuerda que para ver la pid de la shell donde ejecutas el programa debes ejecutar:
$ echo $$
Categorías : Programación
Referencias : No hay referencias »



Referencias
No hay referencias