procesos - Inicio - Universidad Pontificia Bolivariana

Anuncio
PROCESOS
Sistemas Distribuidos
Alvaro Ospina Sanjuan
Universidad Pontificia Bolivariana
Medellín 2010
Proceso

Abstracción de un programa en ejecución

Consiste en los siguientes elementos:

Contexto del programa (status del programa)

Directorio de trabajo

Archivos y directorios
derecho el programa

Credenciales o derechos de acceso del programa

Cantidad de memoria y otros recursos del sistema
asignados
sobre
los
cuales
tiene
Proceso

Abstracción de un programa en ejecución

Entidad activa

Actividad de la CPU


Sistemas procesamiento por lotes

Sistemas tiempo compartido

Sistemas monousuario
Conformado por:

Código del programa

Pila

Datos
jobs
tasks
program
Estados de un Proceso
1
EN
EJECUCIÓN
4
3
BLOQUEADO
2
LISTO
1. Se bloquea en espera de datos
2. Los datos están disponibles
3. Se asigna a la CPU por el fijador del kernel
4. Se le quita la CPU
En ejecución, Listo o preparado, Bloqueado, Nuevo, Espera
Implantación

Tabla de procesos: Observarla en linux con
“??”

Demonios: Procesos creados por el SO para
ejecución permanente. En linux terminan en “d”
Atributos de un proceso:
• Todos los procesos tiene un PID o Process ID,
porque?

•
•
El PID es único
Todo los procesos tiene un proceso padre que es el proceso que
lo inició
– Excepto el proceso 0 el cual es iniciado por el kernel
Llamadas para Procesos en C
(linux)

pid_t fork(void): Crea un proceso, donde el hijo es copia
exacta del padre. La función retorna al proceso hijo “0” y
al proceso padre el pid del hijo.

int execv(const char *path, char * argv[]): Reemplaza
la imagen de un proceso.

pid_t wait( int * stat_loc): Suspende al padre hasta que
llegue el hijo o una señal.

void _exit( int status): Termina el proceso y lo envía
donde el padre.
Ejercicios de procesos

Ejercicio 1

Ejercicio 2

Ejercicio 3

Ejercicio 4

Ejercicio 5
Ejercicio 1
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
int main(void){
printf("\nSoy el proceso: %d\n", getpid());
printf("Mi proceso padre es: %d\n", getppid());
printf("Y mi propietario es: %d\n\n", getuid());
_exit(0);
}
Ejercicio 2
#include
#include
#include
#include
<sys/types.h>
<sys/wait.h>
<unistd.h>
<stdio.h>
int main (void){
pid_t childpid;
int status;
childpid = fork();
if (childpid == -1) {
perror("Ha fallado el fork");
_exit(1);
} else if (childpid == 0)
fprintf(stderr,"Soy el hijo con pid = %d y mi papa es %d\n", getpid(),getppid());
else if (wait(&status) != childpid)
fprintf(stderr, "Algo sacó al padre del wait\n");
else
fprintf(stderr, "Soy el padre con pid = %d y el pid del hijo es = %d\n",getpid(), childpid);
_exit(0);
}
Ejercicio 3
#include
#include
#include
#include
#include
<sys/types.h>
<sys/wait.h>
<unistd.h>
<stdio.h>
<stdlib.h>
int main(void) {
pid_t childpid;
int status;
if ((childpid = fork()) == -1) {
perror("Error en el fork");
_exit(1);
} else if (childpid == 0) {
/* código del hijo */
if (execl("/bin/ls", "ls", NULL) < 0) {
perror("Ha fallado la ejecución de ls");
_exit(1);
}
} else wait(&status); /* código del padre */
_exit(0);
}
Ejercicio 4
#include
#include
#include
#include
<sys/types.h>
<sys/wait.h>
<unistd.h>
<stdio.h>
int main (void){
pid_t childpid;
int status;
if ((childpid = fork()) == -1) {
perror("Ha fallado fork");
_exit(1);
} else if (childpid == 0){
fprintf(stderr, "Soy el hijo con pid = %d\n", getpid()); sleep(5);
} else{
sleep(3);
fprintf(stderr, "Soy el padre con pid = %d y mi hijo tiene el pid = %d\n",getpid(), childpid);
wait(&status);
}
_exit(0);
}
Estados de un Proceso
El proceso original sigue por la
parte del else y el nuevo proceso
por el then.
then De esta manera, el
proceso original, por ejemplo,
podría seguir atendiendo nuevos
clientes que quieran conectarse
a nuestro programa por un
socket, mientras que el proceso
hijo podría atender a un cliente
que acaba de conectarse y que
es el que ha provocado que
lancemos el fork().
Proceso

Hay que tener en cuenta que se ha duplicado todo el
espacio de memoria. Por ello, ambos procesos tienen todas
las variables repetidas, pero distintas. Si el proceso original
toca la variable "contador", el proceso hijo no verá
reflejado el cambio en su versión de "contador".

si antes del fork() tenemos, por ejemplo, un flujo abierto
(un flujo a archivo, un socket o cualquier otra cosa),
después del fork() ambos procesos tendrán abierto el
mismo flujo y ambos podrán escribir en él. Es más, uno de
los procesos puede cerrar el flujo mientras que el otro lo
puede seguir teniendo abierto.
Proceso

Proceso tiene su propia memoria, es imposible en Linux
que un proceso se “meta” en la memoria de otro.
Proceso

Una vez lanzado el proceso hijo, el padre puede "esperar"
que el hijo termine. Para ello tenemos la función wait().
wait()

Una vez que salimos del wait(), tenemos unas macros que
nos permiten evaluar el contenido de estadoHijo
– WIFEXITED(estadoHijo) es 0 si el hijo ha terminado de
una manera anormal (caida, matado con un kill, etc).
Distinto de 0 si ha terminado porque ha hecho una
llamada a la función exit()
– WEXITSTATUS(estadoHijo) devuelve el valor que ha
pasado el hijo a la función exit(), siempre y cuando la
macro anterior indique que la salida ha sido por una
llamada a exit().
Respuesta del Ejercicio6

Hijo : Mi pid es 4303. El pid de mi padre es 4302

Hijo : variable = 1. La cambio al valor 2

Padre : Mi pid es 4302. El pid de mi hijo es 4303

Hijo : variable = 2 y salgo

Padre : Mi hijo ha salido. Devuelve 33

Padre : variable = 1

-----------------

(program exited with code: 0)

Press return to continue
Agradecimientos

A la profesora Ana Oviedo por su colaboración en este
material.
Descargar