Gestor de Memoria - Práctica 3 OS 1.0
Simulador de gestión de memoria con algoritmos de Primer Hueco y Siguiente Hueco.
Cargando...
Buscando...
Nada coincide
sim_engine.c
Ir a la documentación de este archivo.
1#include "sim_engine.h"
2#include "ficheros.h"
3#include "file_utils.h"
4#include <stdio.h>
5#include <string.h>
6
8 // Inicializamos la memoria con un único hueco que ocupa toda la memoria disponible
9 m->cant_particiones = 1;
10
11 // El último índice asignado empieza en 0
13
14 // Única partición: Hueco de tamaño MEMORIA_TOTAL al inicio
15 m->particiones[0].dir_inicio = 0;
17 // Estado 0 indica que es un hueco libre
18 m->particiones[0].estado = 0;
19 // Nombre del proceso "HUECO" para indicar que está libre
20 strcpy(m->particiones[0].nombre_proceso, "HUECO");
21}
22
24 // Recorremos todas las particiones y mostramos su estado en formato [dir_inicio nombre_proceso tamano]
25 for (int i = 0; i < m->cant_particiones; i++) {
26 printf("[%d %s %d]", m->particiones[i].dir_inicio, m->particiones[i].nombre_proceso, m->particiones[i].tamano);
27 }
28 printf("\n");
29}
30
31int ocupar_memoria(Memoria *m, int indice_hueco, Proceso p) {
32 // Obtenemos un puntero a la partición hueco que vamos a ocupar
33 Particion *hueco = &m->particiones[indice_hueco];
34
35 // Verificamos que el hueco es libre y que cabe el proceso si no, error
36 if (hueco->estado != 0 || hueco->tamano < p.mem_requerida) {
37 printf("ERROR: no se puede asignar el proceso \n");
38 return 0;
39 }
40
41 // CASO A: Ajuste Exacto (El proceso ocupa todo el hueco)
42 if (hueco->tamano == p.mem_requerida) {
43 hueco->estado = 1;
44 strcpy(hueco->nombre_proceso, p.nombre);
45 } else {
46 // CASO B: Hay que dividir (El hueco es más grande)
47 // 1. Verificamos que no desbordamos el array
48 if (m->cant_particiones >= MAX_PARTICIONES) return 1;
49
50 // 2. DESPLAZAMIENTO: Movemos todo una posición a la derecha
51 // desde el final hasta el siguiente al hueco actual
52 for (int i = m->cant_particiones; i > indice_hueco + 1; i--) {
53 m->particiones[i] = m->particiones[i - 1];
54 }
55
56 int tamano_restante = hueco->tamano - p.mem_requerida;
57 int dir_nueva = hueco->dir_inicio + p.mem_requerida;
58
59 // 3. Crear el NUEVO hueco restante en la posición siguiente (i+1)
60 m->particiones[indice_hueco + 1].dir_inicio = dir_nueva;
61 m->particiones[indice_hueco + 1].tamano = tamano_restante;
62 m->particiones[indice_hueco + 1].estado = 0; // LIBRE
63 strcpy(m->particiones[indice_hueco + 1].nombre_proceso, "HUECO");
64
65 // 4. Actualizar el hueco actual para convertirlo en PROCESO
66 hueco->tamano = p.mem_requerida;
67 hueco->estado = 1; // OCUPADO
68 strcpy(hueco->nombre_proceso, p.nombre);
69
70 // 5. Actualizamos contadores
72 }
73 // Actualizamos el puntero para Next Fit (para cuando lo implementemos)
74 m->ultimo_indice_asignado = indice_hueco;
75
76 return 1; // Éxito
77}
78
80 // Recorremos hasta el penúltimo elemento
81 for (int i = 0; i < m->cant_particiones - 1; i++) {
82 // Si la partición actual y la siguiente son huecos, las unimos
83 if (m->particiones[i].estado == 0 && m->particiones[i+1].estado == 0) {
84 // 1. Sumamos tamaños de las particiones
85 m->particiones[i].tamano += m->particiones[i+1].tamano;
86 // 2. Movemos todas las particiones siguientes una posición a la izquierda
87 for (int j = i + 1; j < m->cant_particiones - 1; j++) {
88 m->particiones[j] = m->particiones[j+1];
89 }
90 // 3. Actualizamos el contador de particiones
92 // 4. Retrocedemos el índice para revisar la nueva partición fusionada
93 i--;
94
95 printf("[DEBUG] Compactacion realizada del proceso %s\n", m->particiones[i].nombre_proceso);
96 }
97 }
98}
99
100bool liberar_proceso(Memoria *m, char *nombre_proceso) {
101 for (int i = 0; i < m->cant_particiones; i++) {
102 // Si encontramos el proceso y esta ocupado, lo liberamos
103 if (m->particiones[i].estado == 1 && strcmp(m->particiones[i].nombre_proceso, nombre_proceso) == 0) {
104 // 1. Lo convertimos en hueco pasando a estado 0
105 m->particiones[i].estado = 0;
106 strcpy(m->particiones[i].nombre_proceso, "HUECO");
107 printf("[DEBUG] Proceso %s liberado en dir %d\n", nombre_proceso, m->particiones[i].dir_inicio);
108
109 // 2. Compactamos la memoria para unir huecos adyacentes
110 compactar(m);
111
112 return true;
113 }
114 }
115 return false;
116}
117
118int buscar_hueco(Memoria *m, int mem_requerida, TipoAlgo tipo_algo) {
119 // Algoritmo Primer Hueco
120 if (tipo_algo == ALGO_PRIMER_HUECO) {
121 // Recorremos todas las particiones buscando el primer hueco que quepa
122 for (int i = 0; i < m->cant_particiones; i++) {
123 // Si es un hueco libre y cabe el proceso
124 if (m->particiones[i].estado == 0 && m->particiones[i].tamano >= mem_requerida) {
125 return i; // Devolvemos el índice del hueco encontrado
126 }
127 }
128 }
129
130 // Algoritmo Siguiente Hueco
131 if (tipo_algo == ALGO_SIGUIENTE_HUECO) {
132 // El punto de partida es el último índice asignado
133 int inicio = m->ultimo_indice_asignado;
134 // Sacamos el total de particiones para poder hacer la búsqueda circular
135 int total = m->cant_particiones;
136
137 // Recorremos todas las particiones empezando desde 'inicio' de forma circular
138 for (int j = 0; j < total; j++) {
139 // Calculamos el índice real con módulo para la circularidad
140 int i = (inicio + j) % total;
141
142 // Si es un hueco libre y cabe el proceso devolvemos su índice en la memoria
143 if (m->particiones[i].estado == 0 && m->particiones[i].tamano >= mem_requerida)
144 return i;
145 }
146 }
147
148 return -1;
149}
150
151int alinear_size(int size) {
152 int tam_final; // Variable para el tamaño final alineado
153
154 // Si el tamaño es mayor que la unidad mínima, lo alineamos
155 if (size > UNIDAD_MINIMA) {
156 int bloques = size / 100; // Cantidad de bloques completos de 100
157 if (size % 100 != 0) // Si hay resto
158 tam_final = UNIDAD_MINIMA * bloques + 100; // Sumamos un bloque más
159 else
160 tam_final = bloques * 100; // Exacto, no hay resto
161 } else
162 tam_final = UNIDAD_MINIMA; // Si es menor o igual a 100, lo ajustamos a 100
163
164 return tam_final;
165}
166
167bool asignar_proceso(Memoria *m, Proceso p, TipoAlgo tipo_algo) {
168 // Calculamos el tamaño real alineado
169 int tam_real = alinear_size(p.mem_requerida);
170
171 // [Opcional] Debug para ver el cambio
172 if (tam_real != p.mem_requerida)
173 printf("[DEBUG Alineacion] Proceso %s pide %d pero ocupara %d\n", p.nombre, p.mem_requerida, tam_real);
174
175 // Buscamos un hueco adecuado con el tamaño real y el algoritmo indicado
176 int pos_mem = buscar_hueco(m, tam_real, tipo_algo);
177
178 // Si no se encontró hueco, devolvemos false
179 if (pos_mem == -1)
180 return false;
181
182 // Actualizamos el requerimiento de memoria del proceso al tamaño real
183 p.mem_requerida = tam_real;
184
185 // Intentamos ocupar el hueco encontrado
186 return ocupar_memoria(m, pos_mem, p);
187}
188
189void avanzar_tiempo(Memoria *m, Proceso procesos[], int num_procesos, int *reloj_actual, TipoAlgo algo, const char* ruta_log) {
190 printf("\n-----INSTANTE %d----\n", *reloj_actual);
191
192 // Paso 1 y 2 -> Envejecimiento y finalización de procesos
193 for (int i = 0; i < num_procesos; i++) {
194 // Solo procesamos los que están en memoria y no han finalizado
195 if (procesos[i].en_memoria && !procesos[i].finalizado) {
196 // DEBUG: Ver cuánto le queda antes de restar ---
197 printf("[DEBUG Vida] %s tiene %d ticks restantes.\n", procesos[i].nombre , procesos[i].t_restante);
198 procesos[i].t_restante--; // Disminuimos su tiempo restante
199
200 // Si ya no le queda tiempo, lo finalizamos
201 if (procesos[i].t_restante <= 0) {
202 printf("-> FIN: El proceso %s ha terminado. Liberando memoria...\n", procesos[i].nombre);
203
204 // Liberamos su memoria
205 liberar_proceso(m, procesos[i].nombre);
206
207 // Marcamos el proceso como finalizado
208 procesos[i].en_memoria = false;
209 procesos[i].finalizado = true;
210 }
211 }
212 }
213
214 // Paso 3 -> Llegada de nuevos procesos
215 for (int i = 0; i < num_procesos; i++) {
216 // Se busca proceso que no esté en memoria, no finalizado y que haya llegado o su momento ya haya pasado
217 if (!procesos[i].en_memoria && !procesos[i].finalizado && procesos[i].t_llegada <= *reloj_actual) {
218 printf("-> LLEGADA: %s intenta entrar (Requiere %d)\n", procesos[i].nombre, procesos[i].mem_requerida);
219
220 // Intentamos asignarlo en memoria
221 if (asignar_proceso(m, procesos[i], algo)) {
222 printf("EXITO: %s asignado en memoria \n", procesos[i].nombre);
223 procesos[i].en_memoria = true;
224 // Inicializamos su tiempo restante
225 procesos[i].t_restante = procesos[i].t_ejecucion;
226 } else {
227 // No se pudo asignar, se queda esperando, al ser t_llegada <= reloj_actual, volverá a intentar en el siguiente tick
228 printf("ESPERA: No hay hueco para %s. Esperara al siguente tick \n", procesos[i].nombre);
229 }
230 }
231 }
232
233 guardar_estado(ruta_log, m, *reloj_actual);
234
235 (*reloj_actual)++;
236}
void guardar_estado(const char *ruta, Memoria *m, int instante)
Guarda el estado actual de la memoria en un archivo de log.
Definition ficheros.c:64
Módulo de entrada/salida para la simulación de memoria.
Librería de utilidades para operaciones de E/S con descriptores de fichero.
#define MEMORIA_TOTAL
Tamaño total de la memoria simulada (en unidades).
Definition sim_engine.h:36
#define UNIDAD_MINIMA
Unidad mínima de asignación. Toda memoria se alinea a múltiplos de este valor.
Definition sim_engine.h:39
#define MAX_PARTICIONES
Máximo número de particiones simultáneas en memoria.
Definition sim_engine.h:42
void avanzar_tiempo(Memoria *m, Proceso procesos[], int num_procesos, int *reloj_actual, TipoAlgo algo, const char *ruta_log)
Avanza un tick en la simulación.
Definition sim_engine.c:189
bool asignar_proceso(Memoria *m, Proceso p, TipoAlgo tipo_algo)
Asigna un proceso a la memoria.
Definition sim_engine.c:167
int ocupar_memoria(Memoria *m, int indice_hueco, Proceso p)
Ocupa un hueco de memoria con un proceso.
Definition sim_engine.c:31
void mostrar_estado(Memoria *m)
Muestra el estado actual de la memoria en consola.
Definition sim_engine.c:23
void inicializar_memoria(Memoria *m)
Inicializa la memoria con un único hueco libre.
Definition sim_engine.c:7
int buscar_hueco(Memoria *m, int mem_requerida, TipoAlgo tipo_algo)
Busca un hueco adecuado según el algoritmo especificado.
Definition sim_engine.c:118
void compactar(Memoria *m)
Compacta la memoria uniendo huecos adyacentes.
Definition sim_engine.c:79
bool liberar_proceso(Memoria *m, char *nombre_proceso)
Libera un proceso de la memoria.
Definition sim_engine.c:100
int alinear_size(int size)
Alinea un tamaño a múltiplos de UNIDAD_MINIMA.
Definition sim_engine.c:151
Motor de simulación de gestión de memoria con particiones variables.
TipoAlgo
Algoritmos de asignación de memoria disponibles.
Definition sim_engine.h:102
@ ALGO_PRIMER_HUECO
Definition sim_engine.h:103
@ ALGO_SIGUIENTE_HUECO
Definition sim_engine.h:104
Estructura principal que representa la memoria del sistema.
Definition sim_engine.h:90
int ultimo_indice_asignado
Definition sim_engine.h:93
Particion particiones[MAX_PARTICIONES]
Definition sim_engine.h:91
int cant_particiones
Definition sim_engine.h:92
Estructura que representa una partición de memoria.
Definition sim_engine.h:77
char nombre_proceso[10]
Definition sim_engine.h:81
int dir_inicio
Definition sim_engine.h:78
Estructura que representa un proceso en el simulador.
Definition sim_engine.h:57
char nombre[10]
Definition sim_engine.h:58
int t_ejecucion
Definition sim_engine.h:61
int t_restante
Definition sim_engine.h:65
bool finalizado
Definition sim_engine.h:67
int mem_requerida
Definition sim_engine.h:60
bool en_memoria
Definition sim_engine.h:66