funcs - programación concurrente

4
PROGRAMACIÓN CONCURRENTE COMPILACIÓN Y EJECUCIÓN DE PROGRAMAS C. LLAMADAS DEL SISTEMA RELACIONADAS CON LOS PROCESOS. 1.- Compilación y ejecución de programas C. Un programa en C se escribe mediante un editor, dándole al fichero que lo contiene un nombre con la extensión .c. Para compilarlo se usa la orden gcc que es el compilador de C. La sintaxis es: gcc nombre_fichero dando como resultado un fichero denominado a.out que será el ejecutable. Si se quiere que el ejecutable tenga otro nombre distinto se usará la opción -o del compilador de la siguiente forma: gcc -o nombre_fichero_ejecutable nombre_fichero_compilar Este compilador no se detiene al encontrar el primer error, sino que continúa mientras puede. 2.- Llamadas del sistema relacionadas con los procesos. 2.1.- Creación de procesos: fork. La llamada al sistema fork () es la única que permite crear un nuevo proceso. El proceso que invoca a fork () se llama proceso padre y el proceso creado es el proceso hijo. El contenido del proceso hijo es identico al contenido del proceso padre. El nuevo proceso hereda algunas de las características del antiguo proceso, tales como el identificador de usuario y de grupo, la prioridad, etc, excepto el identificador del proceso que será distinto para el proceso hijo, puesto que se le asigna uno nuevo. El proceso hijo comienza su ejecución mientras que el proceso padre continua la suya, por la siguiente instrucción después del fork (). Sólo se puede hacer una llamada fork(), que devuelve dos valores, uno por proceso. Fork () devuelve un cero al proceso hijo y un valor distinto de cero (el identificador del proceso hijo) al proceso padre. Si la llamada a fork () falla, devolverá el valor -1 al proceso padre. El siguiente ejemplo muestra el uso de está llamada al sistema. #include <stdio.h> main () { int pid; if ((pid=fork ())==-1) { printf (“Error en la llamada a fork”); } else if (pid==0) { /* Código que va a ejecutar el proceso hijo. */ © E.G.R. 1

Upload: manfred-marcano

Post on 19-Jan-2016

2 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: FUNCS - Programación Concurrente

PROGRAMACIÓN CONCURRENTE

COMPILACIÓN Y EJECUCIÓN DE PROGRAMAS C. LLAMADASDEL SISTEMA RELACIONADAS CON LOS PROCESOS.

1.- Compilación y ejecución de programas C.

Un programa en C se escribe mediante un editor, dándole al fichero que locontiene un nombre con la extensión .c. Para compilarlo se usa la orden gcc que es elcompilador de C. La sintaxis es: gcc nombre_ficherodando como resultado un fichero denominado a.out que será el ejecutable. Si se quiereque el ejecutable tenga otro nombre distinto se usará la opción -o del compilador de lasiguiente forma: gcc -o nombre_fichero_ejecutable nombre_fichero_compilar

Este compilador no se detiene al encontrar el primer error, sino que continúamientras puede.

2.- Llamadas del sistema relacionadas con los procesos.

2.1.- Creación de procesos: fork.

La llamada al sistema fork () es la única que permite crear un nuevo proceso. Elproceso que invoca a fork () se llama proceso padre y el proceso creado es el procesohijo. El contenido del proceso hijo es identico al contenido del proceso padre. El nuevoproceso hereda algunas de las características del antiguo proceso, tales como elidentificador de usuario y de grupo, la prioridad, etc, excepto el identificador delproceso que será distinto para el proceso hijo, puesto que se le asigna uno nuevo.

El proceso hijo comienza su ejecución mientras que el proceso padre continua lasuya, por la siguiente instrucción después del fork (). Sólo se puede hacer una llamadafork(), que devuelve dos valores, uno por proceso. Fork () devuelve un cero al procesohijo y un valor distinto de cero (el identificador del proceso hijo) al proceso padre. Si lallamada a fork () falla, devolverá el valor -1 al proceso padre.

El siguiente ejemplo muestra el uso de está llamada al sistema.

#include <stdio.h>main (){

int pid;

if ((pid=fork ())==-1){printf (“Error en la llamada a fork”);}

else if (pid==0) {

/* Código que va a ejecutar el proceso hijo. */

© E.G.R. 1

Page 2: FUNCS - Programación Concurrente

printf ("Soy el proceso hijo"); }

else { /* Código que va a ejecutar el proceso padre. */

printf ("Soy el proceso padre"); }

}

2.2.- Terminación de procesos: exit y wait.

Una situación muy típica es que cuando un proceso crea a otro, el proceso padrese quede esperando a que termine el hijo antes de continuar su ejecución. Un ejemplo deesta situación es la forma de operar de los intérpretes de órdenes. Cuando se escribe unaorden, el shell arranca un proceso para ejecutar dicha orden y no devuelve el controlhasta que no se ha ejecutado completamente.

Para poder sincronizar los procesos padre e hijo, se emplean las llamadas exit ywait.

La llamada al sistema exit (estado) finaliza la ejecución de un proceso ydevuelve el valor de estado al sistema. Si el proceso padre del que ejecuta la llamada aexit (estado) esta ejecutando una llamada a wait (estado), se le notifica la terminaciónde su proceso hijo y se le envían los 8 bits menos significativos de estado.

Exit (estado) es una de las pocas llamadas que no devuelve ningún valor. Eslógico, ya que el proceso que la llama deja de existir después de haberla ejecutado.

La llamada al sistema wait (estado) suspende la ejecución del proceso que lainvoca hasta que su proceso hijo haya terminado. Estado es la variable donde se va aalmacenar el valor que el proceso hijo le envía al proceso padre mediante la llamada aexit (estado) y que da idea de la condición de finalización del proceso hijo. Si se deseaignorar este valor, se puede pasar a wait (estado) un puntero NULL.

Si durante la llamada a wait (estado) se produce algún error, la funcióndevuelve -1.

Exit (estado) y wait (estado) se suelen usar para conseguir que el proceso padreespere a la terminación de su proceso hijo. Una secuencia de código para realizar estaoperación puede ser:

#include <stdio.h>main (){ int estado;

if ((pid=fork ())==-1){printf (“Se ha producido un error en la creación del proceso hijo”)

}else if (pid==0)

} printf ("Soy el proceso hijo");

© E.G.R. 2

Page 3: FUNCS - Programación Concurrente

exit (10);}

else{wait (&estado);printf ("Soy el proceso padre");printf ("El proceso hijo devuelve", estado); }

}

Se puede observar en el ejemplo que el proceso padre espera hasta que elproceso hijo termine su ejecución y luego continua. Esta llamada al sistema es la queusa el proceso del Shell que se genera cuando el usuario se conecta con el entorno.

2.3.- Información sobre procesos.

Existen un conjunto de llamadas al sistema necesarias para conocer y fijaralgunos de los parámetros de un proceso, las cuales describen cómo se relaciona elproceso con el resto del sistema.

2.3.1.- Identificadores de proceso.

Todo proceso tiene asociados dos números desde el momento de su creación: elidentificador de proceso y el identificador del proceso padre.

El identificador de proceso (PID) es un número entero positivo que actúa amodo de nombre del proceso. El identificador del proceso padre (PPID) es el PID delproceso que ha creado al actual. El PID de un proceso no cambia durante el tiempo devida de éste; sin embargo, su PPID sí puede variar. Esta situación se da cuando elproceso padre muere, pasando el PPID del proceso hijo a tomar el valor 1.

Para conocer los valores de PID y PPID se utilizan las llamadas getpid () ygetppid (). Es decir, son llamadas al sistema que devuelven al proceso que las solicita elidentificador de él mismo y el identificador del proceso padre respectivamente. Estasllamadas nunca van a fallar.

El objetivo de conocer el identificador de un proceso o el de su padre, estriba enla necesidad que tienen los procesos de conectarse entre sí mediante tuberías,semáforos, o simplemente mandándose señales. Tarea para la cual es imprescindibleconocer ambos valores.

En Unix, los procesos van a estar agrupados en conjuntos de procesos que tienenalguna característica común (por ejemplo, tener un mismo proceso padre). A estosconjuntos se les conoce como grupos de procesos y desde el sistema son controlados através de un identificador de grupo de procesos. Para conocer a qué grupo pertenece unproceso, se utiliza la llamada getpgrp ().

El identificador de grupo de procesos es heredado por los procesos hijo despuésde una llamada a fork (), pero también puede cambiarse creando un nuevo grupo deprocesos. Esto se consigue con la llamada setpgrp (). Esta llamada hace que el proceso

© E.G.R. 3

Page 4: FUNCS - Programación Concurrente

actual se convierta en el líder de un grupo de procesos. El identificador de este grupo vaa coincidir con el PID del proceso que realiza la llamada y es el valor devuelto por ella.Si la llamada falla, devolverá el valor -1.

El ejemplo siguiente muestra un programa que crea un proceso hijo. Losprocesos padre e hijo van a mostrar su PID, PPID y su identificador de grupo deprocesos. Pasados 5 segundos, el proceso padre va a morir, y el hijo va a mostrar susnuevos PID, PPID e identificador de grupo de procesos. Pasados 10 segundos, elproceso hijo se va a convertir en el líder de un nuevo grupo de procesos y va a mostrarsus identificadores.

#include <stdio.h>main (){

if (fork ()==0){/* Código del proceso hijo. */printf ("Soy el proceso hijo mi PID es %d, mi PPID es %d, y el ID degrupo es %d\n", getpid (), getppid (), getpgrp());sleep (10); printf ("Soy el proceso hijo y transcurrido 10 segundos, mi PID es %d,mi PPID es %d, y el ID de grupo es %d\n", getpid (), getppid (),getpgrp());setpgrp();printf ("Soy el proceso hijo y líder de un grupo de procesos. Ahora miPID es %d, mi PPID es %d, y el ID de grupo es %d\n", getpid (),getppid (), getpgrp());exit (0);}

/* Código que va a ejecutar el proceso padre. */sleep (5);printf ("Soy el proceso padre y transcurrido 5 segundos mi PID es %d, mi PPIDes %d, y el ID de grupo es %d\n", getpid (), getppid (), getpgrp());exit (0);

}

2.3.2.- Identificadores de usuario y de grupo.

Cada proceso tiene asociado un identificador de usuario UID y un identificadorde grupo GID. El UID identifica al usuario que es responsable de la ejecución delproceso y el GID al grupo al cual pertenece el usuario.

Se pueden conocer los valores que toman estos identificadores mediante lasllamadas getuid () que devuelve el identificador de usuario y getgid () que devuelve elidentificador del grupo.

Los procesos hijos heredan estos valores del proceso padre.

© E.G.R. 4