Publicado el 8 de Mayo del 2019
758 visualizaciones desde el 8 de Mayo del 2019
530,9 KB
47 paginas
Creado hace 12a (03/08/2011)
Llamadas al Sistema para la
Creación de Procesos
Transparencias realizadas por M. Curiel. Se utiliza material ya publicado en la WEB
y elaborado por todos los prof. que hemos dado el curso.
Llamada al Sistema Fork
La única forma que existe en UNIX
para crear un proceso es
duplicando un proceso ya existente.
El proceso init es el ancestro de todos
los procesos que se crean durante una
sesión.
El proceso que hace una solicitud para
la creación de otro proceso se conoce
como proceso padre, y el proceso
creado se conoce como proceso hijo.
Llamada al Sistema Fork
Después de la duplicación, ambos
procesos (padre e hijo) son idénticos
salvo en el PID (Process ID). Es decir,
ambos procesos tienen el mismo
espacio de direcciónes: el área de
datos, la pila y ambos continúan
ejecutando el mismo código.
Es posible que el proceso hijo
reemplace posteriormente el código
que ejecuta su padre por otro
programa.
Llamada al Sistema Fork
Un proceso crea otro proceso utilizando la
llamada al sistema fork
#include <sys/types.h>
#include <unistd.h>
Librerías que se
deben Incluir.
pid_t fork(void)
Devuelve 0 al hijo y el PID del hijo
Al padre.
Imagen en la Memoria
de Procesos Unix
Pila
Datos
Código
Proceso 1
Proceso 2
Proceso 3
Pila
Datos
Código
Pila
Datos
Código
Pila
Datos
Código
main() {
PC
….
pidhijo = fork();
if (pidhijo == 0) {
printf(“soy el padre”),
else
printf(“soy el hijo);
}
proceso1
Pila
Datos
Código
Pila
Datos
Código
Detalle de la Memoria Principal: Código
del Proceso 1, antes de ejecutar la llamada al
Sistema fork()
Memoria Principal
main() {
PC
….
pidhijo = fork();
if (pidhijo == 0) {
printf(“soy el padre”),
else
printf(“soy el hijo);
}
Detalle de la Memoria Principal:
Qúe pasa en la memoria cuando se
ejecuta la llamada al sistema fork?.
Padre
Hijo
Pila
Datos
Código
Pila
Datos
Código
Pila
Datos
Código
Memoria Principal
pidhijo = 5096
….
pidhijo = 0
…
Detalle de la Memoria Principal:
Valor de la variable pidhijo en ambos
procesos
Padre
Hijo
Pila
Datos
Código
Pila
Datos
Código
Pila
Datos
Código
Memoria Principal
main() {
PC
….
pidhijo = fork();
if (pidhijo == 0) {
printf(“soy el hijo”),
else
printf(“soy el padre);
}
Detalle de la Memoria Principal: Ejecución del
proceso padre después del fork
Padre
Hijo
Pila
Datos
Código
Pila
Datos
Código
Pila
Datos
Código
Memoria Principal
main() {
….
pidhijo = fork();
if (pidhijo == 0) {
printf(“soy el hijo”),
else
printf(“soy el padre);
PC
}
Detalle de la Memoria Principal: Ejecución
del proceso Padre después del fork
Padre
Hijo
Pila
Datos
Código
Pila
Datos
Código
Pila
Datos
Código
Memoria Principal
main() {
….
pidhijo = fork();
if (pidhijo == 0) {
printf(“soy el hijo”),
else
printf(“soy el padre);
PC
}
Detalle de la Memoria Principal: Ejecución
del proceso hijo después del fork
Padre
Hijo
Pila
Datos
Código
Pila
Datos
Código
Pila
Datos
Código
Memoria Principal
main() {
PC
….
pidhijo = fork();
if (pidhijo == 0) {
printf(“soy el hijo”),
else
printf(“soy el padre);
}
Detalle de la Memoria Principal: Ejecución del
proceso hijo después del fork
Padre
Hijo
Pila
Datos
Código
Pila
Datos
Código
Pila
Datos
Código
Memoria Principal
main() {
PC
….
pidhijo = fork();
if (pidhijo == 0) {
printf(“soy el hijo”),
else
printf(“soy el padre”);
}
Detalle de la Memoria Principal: Ejecución
del proceso hijo después del fork
Padre
Hijo
Pila
Datos
Código
Pila
Datos
Código
Pila
Datos
Código
Memoria Principal
Qué hereda el proceso hijo?
Cada proceso tiene un identificador (PID). Las
llamadas al sistema getpid() y getppid()
permiten obtener el PID del propio proceso y el
de su padre, respectivamente.
El hijo hereda la mayor parte de los atributos del
padre incluyendo el ambiente y los privilegios.
También hereda alguno de los recursos del padre
tales como archivos y dispositivos abiertos.
Los tiempo de uso de CPU para el hijo son
inicializados en 0.
Qué hereda el proceso hijo??
El hijo no obtiene los bloqueos que el padre
mantiene.
Si el padre ha colocado una alarma, el hijo no
recibe notificación alguna al momento que
esta expira.
El hijo su ejecución comienza sin señales
pendientes
Ejemplos del uso de la llamada al
sistema fork.
#include <sys/types.h>
#include <unistd.h>
…
main() {
x = 0;
fork();
x = 1;
}
Después del fork existen dos procesos
independientes, cada uno tiene su propia
copia de la variable X.
No están modificando la misma
localidad de memoria.
Ambos procesos están ejecutando la
misma instrucción sobre su copia de la
Variable X
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
main() {
int status, i,nprocesos;
pid_t childpid;
nprocesos = 4;
for (i = 0; i < nprocesos; ++i) {
if ((childpid = fork()) < 0) {
perror("fork:");
exit(1);
}
// Codigo que ejecutaran los hijos
if (childpid == 0) {
printf("Soy el hijo con pid %ld\n", getpid());
exit(0);
}
} //fork
} // main
Abanico de
Procesos
Abanico de Procesos
Valor de la variable i heredado por cada uno de los procesos creados.
Salida del Programa
// Salida al ejecutar el programa
Soy el hijo con pid 3788
Soy el hijo con pid 3790
Soy el hijo con pid 3789
Soy el hijo con pid 3791
Cadena de Procesos
nprocesos = 4;
for (i = 0; i < nprocesos; i++) {
if ((childpid = fork()) < 0) {
perror("fork:");
exit(1);
}
// Codigo que ejecutaran los hijos
if (childpid > 0) //los padres se mueren,
// el hijo sigue en el for.
break;
}
For: CMP i, nprocesos
BEQ i , 4, salir
……. //codigo fork
ADD i,i, 1
JMP For
i = 0
i = 1
i = 2
i = 3
i = 4
Hijo hereda i = 0
pero incrementa
a 1 en la
próxima iteración.
No se
Crean mas hijos
Árbol de Procesos (Padres e hijos
crean procesos)
nprocesos = 3;
for (i = 0; i < nprocesos; ++i) {
if ((childpid = fork()) < 0) {
perror("fork:");
exit(1);
}
}
Valor de i heredado del
padre antes de entrar de
nuevo al for.
Llamada al sistema:Wait
Después de que un padre crea un proceso
hijo, ambos continúan ejecutándose de forma
concurrente.
Si un padre desea esperar porque el hijo
termine, debe ejecutar wait o waitpid.
pid_t wait(int *status)
pid_t waitpid(pid_t pid, int *status, int opciones)
Prototipo de las funciones de librería.
Wait, WaitPid
La llamada al sistema wait detiene al proceso que la
invoca hasta que un hijo de éste termine
(cualquiera). wait regresa de inmediato si el
proceso que la invoca no tiene hijos o si el hijo ya ha
terminado.
Si wait regresa debido a la terminación de un hijo, el
valor devuelto es igual al PID del
proceso que finaliza. De lo contrario devuelve
–1 y pone un valor en errno.
Wait, WaitPid
status es un apuntador a una variable entera. El
proceso que invoca wait debe colocar como
parámetro la dirección de una variable entera. En
esta variable se almacenará el estado devuelto por el
hijo (bits más significativos).
pid_t wait(int *status)
La librería POSIX especifica ciertas macros para analizar el estado
devuelto por el hijo (WIFEXITED, WEXITSTUS, WIFSIGNALED,
WTERMSIG, WIFSTOPPED y WSTOPSIG).
Wait, WaitPid
La función de librería waitpid proporciona un
método para esperar por un hijo en
particular. Tiene tres parámetros. Si pid es igual a
–1, waitpid espera por cualquier proceso. Si pid es
positivo entonces espera al hijo cuyo PID es pid. El
segundo parámetro es la variable donde se
devolverá el status, y el último permite especificar,
por ejemplo, si el padre se bloqueará o no al esperar
por los hijos.
pid_t waitpid(pid_t pid, int *status, int opciones)
Ejemplos: Abanico con Wait
nprocesos = 5;
for (i = 0; i < nprocesos; ++i) {
if ((childpid = fork()) < 0) {
perror("fork:");
exit(1);
}
// Codigo que ejecutaran los hijos
if (childpid == 0) {
printf("Soy el hijo con pid %ld\n", getpid());
exit(0);
}
}
// El padre espera que terminen todos los hijos que creo.
for (i = 0; i < nprocesos; ++i)
wait(&status);
printf("El padre termina\n");
}
Abanico que no es concurrente
for (i = 0; i < nprocesos; ++i) {
if ((childpid = fork()) < 0) {
perror("fork:");
exit(1);
}
// Codigo que ejecutaran los hijos
if (childpid == 0) {
printf("Soy el hijo con pid %ld\n", getpid());
exit(0);
}
wait(&status); // evita la concurrencia
}
Cadena con el Wait
nprocesos = 5;
for (i = 0; i < nprocesos; ++i) {
if ((childpid = fork()) < 0) {
perror("fork:");
exit(1);
}
// Codigo que ejecutaran los hijos
if (childpid > 0)
break;
}
while ((childpid = wait(&status)) != -1);
printf("Soy el hijo con pid %ld, Mi padre es %ld\n",
getpid(), getppid());
i = 0
i = 1
i= 2
i = 3
i = 4
El primer proceso que sale del wait (le retorna -1),
es el primero en i mprimir el mensaje.
Salida del Programa
//Salida al ejecutar el programa
Soy el hijo con pid 3798, Mi padre es 3797
Soy el hijo con pid 3797, Mi padre es 3796
Soy el hijo con pid 3796, Mi padre es 3795
Soy el hijo con pid 3795, Mi padre es 3794
Soy el hijo con pid 3794, Mi padre es 3793
Soy el hijo con pid 3793, Mi padre es 3730
Ejemplo utilizando el valor de status
Se debe incluir wait.h
if ((child_pid = fork()) < 0) {
perror("fork:");
exit(1);
}
// Codigo que ejecutara el hijo
if (child_pid == 0) {
//….
exit(0);
}
// El padre espera el hijo que creo.
while((child_pid = wait(&status)) == -1);
if (!status)
printf("El hijo %ld termino normalmente, el estado devuelto es 0\n",
Comentarios de: Llamadas al Sistema para la Creación de Procesos en Unix (0)
No hay comentarios