¿Qué es un proceso?
Proceso = Programa en ejecución
Cada una de las CPU se tienen que
compartir a ratos con todos los procesos cargados en la memoria RAM.
Cuando un programa usa la CPU y
sale, hay que hacer una especie de instantánea para guardar el contador de
procesos pendientes, donde se ha quedado, etc.
Esto se conoce como el BCP (bloque de control de procesos). Es
una tabla del sistema operativo que guarda la información de la situación de
como se había quedado el programa en el momento de finalizar su tiempo en la
CPU y dejar espacio a otro proceso.
Estados del proceso
Un proceso puede estar en la CPU,
es decir, estará en ejecución.
Puede ser que esté cargado en la
RAM, preparado para que el SO le de paso a la CPU. Estará listo.
O puede ser que esté esperando a
utilizar los recursos que otro proceso ha cogido y hasta que no finalice el
sistema operativo no le va a dejar continuar. Entonces estará bloqueado.
La contienda es como se llama a la pugna que hacen los procesos listos
para conquistar la CPU.
Hay distintos modos de realizar
la asignación de la contienda. Entre otros:
è Round-Robin. Método circular
è Por prioridades. Es decir, el antivirus
tendrá más prioridad que la calculadora, por ejemplo. O el Word al estar
tecleando conseguirá más prioridad de la ventana activa para no dar sensación
de lentitud o ir a saltitos… Pero esto tiene varios problemas, como la
inacción. Es decir, si mientras P1 (proceso 1) está en ejecución por ganar a la
P2 pero entra P3 que tiene mayor prioridad, saldrá P1 y ganará la contienda P3.
è Por tiempos. Mayor prioridad el que
menor tiempo estimado tiene para terminar.
Eso sí, al programar no podremos
controlar los métodos de ordenación de la contienda. No podemos garantizar que
los procesos vayan a coger la CPU en el momento que vayamos a querer.
Procesos en los SSOO
Para ver los procesos en Windows, iremos al Administrador de
Tareas à
Procesos
Para verlos desde la línea de
comandos, en CMD escribiremos tasklist.
Además al hacerlo por línea de comandos veremos el PID, el identificador del proceso.
En Ubuntu podemos verlo en la
terminal con el comando ps.
Si hacemos ps –f también aparecerá el PPID,
el identificador del proceso padre.
Con ps –AF aparecen todos los procesos lanzados en el sistema.
PID y procesos en C
Vamos a realizar las primeras
prácticas con los procesos, los PID y los PPID en el lenguaje C. Para ello
hemos instalado un entorno VitaLinux que
trae ya incorporado el compilador gcc, pero podéis utilizar cualquier
herramienta de vuestra elección que os permita trabajar programando en C.
EXECL
Execl sirve para ejecutar comandos del sistema y cualquier programa.
Los argumentos son (const char *fichero, cons char *arg0, …, char *argN,
(char*)NULL).
Devolverá -1 si hay condición de error.
Veamos un código de ejemplo
#include <stdio.h> #include<unistd.h> void main(){ printf(“Los archivos del directorio son: \n”); execl(“/bin/ls”, “ls”, “-l”, (char *)NULL); printf(“ERROR!!!”); }
Aquí estaremos haciendo un ls –l para ver todos los archivos
del directorio desde donde ejecutemos este programa.
A diferencia de execl,
system ejecutará sólo comandos del
sistema, como podemos ver abajo. Vamos a ver el siguiente programa para
hacernos una idea.
#include <stdio.h> #include <stdlib.h> void main(){ system(“ls –l > ficSalida”); printf(“FIN”); }
Lo que hace el código es guardar el resultado de un ls –l de
la carpeta actual del PATH a un fichero salida.
En la arquitectura cliente – servidor tenemos dentro de un
servidor web un proceso que está escuchando, en listen. Le hacen una petición y
este proceso crea un hijo que sirva la página web al cliente. Una vez
finalizada la tarea, el hijo sale de la memoria al finalizar su tarea. Durante
todo la ejecución, el proceso padre se ha mantenido activo permaneciendo a la
escucha de otras peticiones.
Vamos a ver un programa que nos muestre los identificadores
del proceso actual y de su padre.
#include <stdio.h> #include <stdlib.h> #include <unistd.h> void main(){ pid_t id_pactual, id_padre; id_pactual = getpid(); id_padre = getppid(); printf(“PID actual: %d \n”, id_pactual); printf(“PID padre: %d \n”, id_padre); }Analicemos este código.
- La línea de declaración pid_t nos indica el tipo de variable que será, una que nos sirva para almacenar el número de proceso que tenemos.
- La función getpid() devuelve el id del proceso actual
- Y la función getppid() devuelve el id del padre del proceso actual.
Ahora ya sabemos ver los id de los procesos, pero… ¿cómo se
crean los procesos hijos?
Para eso tenemos la instrucción fork(), que es la encargada de crear un proceso hijo. Es decir, una
copia exacta del proceso padre, pero a partir de ahora independientes.
Estos dos procesos, junto con todos los del sistema,
entrarán en la contienda por la puja de la CPU independientemente. Y por tanto
el control de tiempo también será independiente.
Para poder diferenciar uno de otro lo conseguimos con el valor
devuelto por fork(). Con un ejemplo
se verá más claro.
#include <stdio.h> #include <stdlib.h> #include <unistd.h> void main(){ pid_t pid, hijo_pid; pid = fork(); // Aquí crea el proceso hijo if (pid == -1){ printf(“Ha habido un error”); exit(-1); } if(pid == 0){ // Nos encontramos dentro del proceso hijo printf("soy el proceso hijo \n\t Mi PID es %d. El PID de mi padre es: %d. \n", getpid(), getppid()); } else{ hijo_pid = wait(NULL); printf("Soy el proceso padre: \n\t Mi PID es %d. El PID de mi padre es: %d. \n\t Mi hijo %d terminó. \n", getpid(), getppid(), pid); } }Hay varios puntos que comentar. El primero es que como ya hemos dicho, los procesos pese a estar en un mismo programa, tanto el hijo como el padre son independientes en el momento de ejecutar fork().
Si nos devuelve un valor igual a 0, sabremos que estamos
tratando con el hijo, mientras que cualquier otro valor que no indique una
condición de error nos hará saber que está funcionando el padre.
Dentro del padre tenemos la línea
hijo_pid = wait(NULL);
Con ésta línea indicaremos que va
a esperar a la finalización del proceso hijo, y la variable pid guardará el PID
del padre.
¿Ha quedado claro? Atrevámonos con un ejercicio sencillico.
Ejercicio. Coged
un proceso, cread una variable y guardad un valor. 7, por ejemplo. El proceso
crea un hijo que le suma 5, y el padre le resta 5. Visualiza por pantalla el
resultado de ambas operaciones así como el PID y el PPID de ambos procesos.
Solución.
#include <stdio.h> #include <stdlib.h> #include <unistd.h> void main(){ pid_t pid, hijo; int n = 7; pid = fork(); if (pid == -1){ printf(“Error \n”); exit(-1); } if (pid == 0){ n = n + 5; printf("Soy el hijo. Valor de n = %d.\n Proceso %d, padre %d \n\n", n, getpid(), getppid()); } else{ n = n – 5; printf("Soy el padre. Valor de n = %i.\n Proceso %d, padre %d \n\n", n, getpid(), getppid()); } }
0 comentarios:
Publicar un comentario