Introducción
En los procesadores multiprocesos se pueden distinguir 4 estados principales (listo, bloqueado, suspendido y nuevo).
En ese post se analiza los 4 estados de los procesos en el cual se detalla su descripción como ejemplo de uso y análisis del funcionamiento del sistema operativos multiprocesos.
Además un programa en código C que emula el funcionamiento de los estados de los procesos, si quieren la fuente de este programa, sólo tienen que pedirlo...
Estructura de Datos: Los cuatro estados que puede tener un proceso son: nuevo, listo, suspendido, bloqueado cada estado representa una cola única, y estas se manejan a través de una lista enlazada, por tanto se crea una estructura Nodo y una estructura lista a través de los TAD correspondientes, el código es el siguiente.
Estructura de los Nodos
typedef struct ListaNodo
{
int info;
struct ListaNodo *ant, *sig;
} *pListaNodo,ListaNodo;
typedef struct Estructura de las Listas
{
pListaNodo primero, ultimo, ventana;
int longitud;
} TLista, *Lista;
typedef pListaNodo Ventana;
además se crean varias funciones de implementación de la estructura como iniciar lista, anexar lista , primer lista, ultimo lista , siguiente lista, etc., estas funciones están implementadas en la cabecera tadlista.h
Colas: Para el manejo de las colas se crea una cabecera colas.h, la cual ocupa la lista enlazada y generando nuevas funciones para la implementación de la cola, para ello se crea una variable tipo lista de nombre cola.
typedef Lista Cola;
Luego se crean varias funciones de implementación como iniciar Cola, Vaciar Cola, información de la Cola, etc.
Veamos algunos Ejemplos:
La función adicCola sitúa un nuevo elemento de la cola al final de ésta
void adicCola( Cola col, int elem )
{
ultLista(col);
anxLista(col,elem);
}
La función elimCola elimina el primer elemento de la cola
void elimCola( Cola col )
{
primLista(col);
elimLista(col);
}
int longCola( Cola col ) Retorna la longitud de la cola
{
return col->longitud;
}
Estas funciones son muy importantes para facilitar el manejo de las colas y para el buen funcionamiento del programa.
Estructura del Proceso: cada proceso es una estructura con sus propias variables y a cada
Proceso se le asigna una letra única de identificación, los procesos poseen un valor, una linea de instrucción, un estado y una dirección de memoria.
Cada proceso puede tener un máximo de 10 líneas de instrucción y le corresponde una única dirección de memoria de 10 espacios la cual posee en toda su vida activa
El código de la estructura de los procesos es el siguiente
typedef struct est_procesos
{
int n; Valor del proceso
int linea[10]; linea de instrucción
int bcp; dirección del bcp
char estado; estado del proceso
int mem; linea de memoria asignada
} tproceso,*proceso;
Crear proceso: esta función se encarga de crear un proceso e inicia sus valores iniciales
Cada proceso creado se guarda en un vector de procesos PRO [] este vector es muy importante por que sirve para guardar todos los procesos creados y permite al programa recoger información de un proceso en cualquier momento, los valores del proceso es también su dirección en este Vector
proceso crear_proceso(int n,int l,int memoria)
{
Proceso A; Crea el proceso
A = (proceso) malloc (sizeof (tproceso)); asigna memoria
A->n = 1; valor del proceso
A=vaciar_linea(A);
A->linea[l]=1; linea de instrucción leída
A->estado='n'; estado nuevo
A->mem=memoria; espacio de dirección asignada
return A; retorna el proceso al vector PRO[]
}
Asignación de memoria: Cada proceso tiene asignada una porción de porción de memoria fija de 10 celdas y solo puede ocupar esa parte de la memoria
int memoria [200]; este vector simula la memoria del computador en total puede almacenar 20 porciones de memoria para 20 procesos, por ejemplo un proceso X puede tomar una celda de [10 -19]
Para garantizar que este espacio de memoria sea único para cada proceso se encuentra la función vacio_mem.
La variable mem es una dirección aleatoria de memoria, si esta libre el espacio de memoria retornara la misma dirección, en caso que la dirección esté ocupada buscara la próxima dirección siguiente vacía.
El vector Vacio [] se encarga de almacenar las direcciones no ocupadas
mem=vacio_mem(mem,dato); la función vacio_mem retornara la dirección de memoria a
La variable mem que más tarde se le asignara al proceso
Correspondiente.
int vacio_mem(int n,int dato)
{
int i;
if(memoria[n]==0)
{
memoria[n]=dato; si la memoria no esta asignada retorna la misma
Dirección
return n;
}
else
{
for(i=1;i<=20;i++) En caso contrario busca un espacio de memoria
Vacía
{
if(vacio[i]==0)
{
vacio[i]=dato;
return i*10;
}
}
}
Return 0; en el caso que no haya memoria disponible
Retornara un valor cero
}
Estados del proceso:
Nuevo: es la cola donde se alojan los procesos que se van generando aleatoria mente
Listo: Son los procesos que interactúan con el procesador y lo hacen hasta terminar sus
Instrucciones
Bloqueado: son los procesos que solicitan un recurso de Entrada y salida
Suspendidos: Son los procesos que no tienen asignada una dirección de memoria
Planificador: Una vez cargados todos los procesos a la cola de tipo nueva se pone en marcha la función Planificador, La función planificador se encarga de de seleccionar el proceso que pasara de su estado nuevo a listo, dependiendo de la antigüedad del proceso, siendo seleccionado el proceso a través de una política FIFO (primero que entra primero que sale)
Aquí llama a la función planificador y retornara a la cola listo
listo=planificador(nuevo,listo);
Lista planificador(Lista col,Lista cola)
{
proceso proces;
proces=pro[infoCola(col)]; se recupera el proceso a través del vector PRO []
Confirma que tiene memoria seleccionada
if(proces->mem!=0)
{
primLista(col); primero de la lista
adicCola(cola,infoCola(col)); adiciona a la cola listo
elimCola(col); elimina el proceso de la cola nuevo
flechas();
}
Return cola; retorna la cola a la cola listo
}
Suspendor: esta función se encarga de seleccionar el proceso que no tiene memoria y lo pasa a la cola de estado suspendido.
Aquí llama a la función suspendor y se devuelve a la cola suspendida
suspendido= suspendor(nuevo,suspendido); procesos que no tienen asignada memoria
Lista suspendor(Lista col,Lista sus)
{
proceso proces;
proces=pro[infoCola(col)];
if(proces->mem==0) confirma que el proceso no tenga asignada
Memoria
{
primLista(col);
adicCola(sus,infoCola(col)); mueve el proceso a la cola de estado
Suspendido
ElimCola (col);
}
Bloqueador: esta función selecciona a los procesos que requieren recursos de entrada y salida y pasa el proceso de la cola listo a la cola de estado Bloqueado
Lista bloqueador(Lista col, Lista blo)
{
proceso proces;
proces=pro[infoCola(col)]; recupera el proceso
if(proces->linea[proces->n]==1) pregunta si es del tipo entrada
Salida (1)
{
adicCola(blo,infoCola(col)); pasa el proceso al estado
bloqueado
if(!vaciaCola(col))elimCola(col);
}
return blo; retorna la cola bloqueado
}
Procesador: el procesador se encarga de leer la linea de instrucción del proceso e incrementa en una unidad, solo es capaz de leer un proceso a la vez, y retorna el proceso al final de la cola tipo listo.
Cuando un proceso llega al límite de instrucción que son 10 instrucciones el proceso se elimina automáticamente liberando su memoria para poder ingresar otro proceso
proceso actualizar_proceso(proceso A) función de procesador que actualiza los
{ Datos del proceso
int j;
j=A->n;
j++;
A>n=j; aumenta en uno la instrucción del proceso
A->estado='l';
return A; retorna el proceso
}
Ejemplo:
Este ejemplo es un procesador ejecutando un proceso M
Informaciones Generales Sobre los procesos
En el programa se muestran dos recuadros que muestran toda la información sobre los procesos en ejecución, el recuadro estadística se muestra los valores que posee el proceso en el instante de su ejecución y el recuadro memoria muestra la porción de memoria asignada a ese proceso.
Cuadro Estadísticas: muestras los datos referentes a cada proceso en ejecución:
Proceso: Letra asignada
Instrucción: número de linea de la instrucción que se esta ejecutando
Linea [6] = tipo de instrucción o [E/S]. Si la instrucción no requiere ningún recurso
Externo, entonces se imprime Instruc. En caso de que requiera una
Instrucción [E/S] entonces se imprime [E/S] y el proceso pasaría a estado
Bloqueado.
Estado = muestra su estado listo
Memoria: muestra la porción de memoria asignada a cada proceso en ejecución, en este caso el proceso solo puede ocupar su porción de memoria de 10 celdas que es de 140 a 149
Políticas Generales del programa
En un sistema operativo se utilizan varias políticas de ejecución de sus tareas como es la asignación de memoria, el tipo de prio ridad de los procesos, etc. El uso de estas políticas define y afecta el comportamiento general del sistema.
En este programa se usan varios manejos de implementación para definir el comportamiento de los procesos como son las políticas de asignación de memoria o políticas de prioridad de los procesos.
Políticas sobre la memoria: se ha creado una memoria de 200 celdas de tamaño fijo, la cual puede albergar a 20 procesos activos, cada proceso tiene asignado 10 celdas de memoria y solo puede ocupar esa porción de memoria asignada.
Procesos | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
A |
|
|
|
|
|
|
|
|
| |
B |
|
|
|
|
|
|
|
|
| |
. |
|
|
|
|
|
|
|
|
| |
. |
|
|
|
|
|
|
|
|
| |
Y |
|
|
|
|
|
|
|
|
| |
Z |
Políticas de Prioridad: Para el manejo de los procesos se ha asignado la prioridad FIFO
(First in First out), primero que entra primero que sale, por tanto los procesos mas antiguos en la cola son los primeros que se ejecutan en el procesador
Vista general del programa:
Conclusión
Este post ha tratado de los distintos estados que puede tener un proceso a lo largo de su ejecución, la simulación se ha realizado a través de un programa escrito en C++.
En el software de simulación se ha divido en un archivo con extensión CPP y 4 cabeceras header, la cual la cabecera interface contiene todas las interfaces del programa, las cabeceras cola.h y tadlista.h, contienen toda la estructura de datos del programa.