- Aprender
- Informática
- Ciencias de la computación
- Sistemas operativos
- Traducción de direcciones
Espacios de direcciones y traducción de direcciones
malloc y free hasta las llamadas al sistema que las sustentan. Traduce direcciones paso a paso mediante registros base y límite y mediante segmentación, y observa cómo los gestores de espacio libre colocan solicitudes de distintos tamaños, desde el primer ajuste hasta la asignación por bloques compañeros, mientras mantienen bajo control la fragmentación interna y externa.IntermedioUnidad 3 de 9 del curso Curso de Sistemas operativos
Lo que aprenderás
- Describe el espacio de direcciones que ve un programa en ejecución, por qué el sistema operativo virtualiza la memoria y los objetivos que debe cumplir todo esquema de virtualización de memoria.
- Describe un espacio de direcciones y su organizaciónExplica qué es un espacio de direcciones, cómo se organizan en él el código, el montículo y la pila, y en qué se diferencian las direcciones virtuales de las físicas.
- Evalúa la virtualización de memoria según sus objetivosEvalúa un esquema de virtualización de memoria según su transparencia, eficiencia y protección, y distingue el mecanismo del hardware de las políticas del sistema operativo.
- Describe un espacio de direcciones y su organización
- Distingue la memoria de pila de la de montículo, solicita y libera memoria del montículo con las llamadas estándar, reconoce los errores que pueden provocar y explica de dónde procede esa memoria.
- Asigna y libera memoria con la API de memoriaDistingue la memoria automática de la pila de la memoria del montículo, usa correctamente malloc y free a grandes rasgos y reconoce los principales tipos de errores de memoria.
- Explica cómo el asignador obtiene memoria del sistema operativoDistingue la función del sistema operativo de gestionar el espacio de direcciones de un proceso de la función de la biblioteca de gestionar el montículo, y describe las llamadas al sistema que amplían y reducen la memoria.
- Asigna y libera memoria con la API de memoria
- Explica cómo la reubicación dinámica por hardware convierte cada dirección virtual en una física, qué aportan el hardware y el sistema operativo y cuáles son las limitaciones de este enfoque.
- Traduce direcciones virtuales con los registros base y límiteAplica la reubicación dinámica sumando la base a cada dirección virtual y comprobándola frente al límite, y compárala con la reubicación estática.
- Reparte el trabajo entre el hardware y el sistema operativoEnumera lo que debe proporcionar el hardware y lo que debe hacer el sistema operativo al crear procesos, cambiar de contexto, gestionar excepciones y terminar procesos para que funcionen base y límite.
- Evalúa el mecanismo de base y límiteSopesa la velocidad y la protección de base y límite frente a la memoria que desperdicia, y explica por qué conduce a la segmentación.
- Traduce direcciones virtuales con los registros base y límite
- Asigna a cada segmento lógico de un espacio de direcciones su propia base y límite, traduce y comprueba direcciones con registros de segmento y evalúa qué exige la segmentación al sistema operativo.
- Traduce direcciones segmento a segmentoColoca el código, el montículo y la pila de forma independiente en la memoria física y traduce una dirección calculando su desplazamiento dentro del segmento.
- Identifica el segmento al que se refiere una direcciónDetermina el segmento a partir de los bits superiores de una dirección virtual o de cómo se formó la dirección, y calcula el desplazamiento en binario.
- Gestiona la pila, la protección y la comparticiónTraduce direcciones de pila con un desplazamiento negativo, usa bits de protección por segmento y explica cómo los procesos comparten código de forma segura.
- Proporciona soporte a la segmentación y evalúalaDescribe qué debe hacer el sistema operativo para permitir la segmentación, compara la segmentación de grano grueso y fino y explica la fragmentación externa que la limita.
- Traduce direcciones segmento a segmento
- Explica cómo un gestor de espacio libre lleva el registro de la memoria libre y atiende solicitudes de distintos tamaños, compara estrategias de colocación y razona sobre la fragmentación interna y externa.
- Distingue la fragmentación interna de la externaDefine los dos tipos de fragmentación, identifícalos en ejemplos y explica por qué un asignador del montículo no puede compactar la memoria.
- Registra el espacio libre con una lista de bloques libresDivide y fusiona bloques libres, usa cabeceras para liberar memoria sin indicar el tamaño y construye la lista de bloques libres dentro de la propia memoria libre.
- Compara estrategias de colocaciónAplica mejor, peor, primer y siguiente ajuste a una lista de bloques libres y sopesa su velocidad frente a la fragmentación que causan.
- Usa listas segregadas y asignación por bloques de objetos y por bloques compañerosExplica cómo las listas por tamaño, las cachés de objetos y los bloques compañeros de tamaño potencia de dos aceleran la asignación, y calcula el desperdicio y las fusiones en la asignación por bloques compañeros.
- Distingue la fragmentación interna de la externa
Guía de estudio de Traducción de direcciones
1Una vista privada de la memoria para cada proceso
Un puntero pertenece al proceso que lo usa. Su número por sí solo no identifica una celda de memoria física. Los espacios de direcciones permiten que varios programas permanezcan en memoria mientras cada uno se ejecuta con su propia vista del código y los datos. El sistema operativo y el procesador deben mantener esa vista, traducir los accesos con rapidez e impedir que un programa dañe a otro. Estos objetivos explican tanto la organización que ve un programa como los mecanismos que permanecen ocultos detrás de ella.
1.1 La memoria que ve un proceso
Un programa en ejecución trabaja con un espacio de direcciones: su propia vista de la memoria, con ubicaciones de bytes numeradas. El sistema operativo coloca la memoria del programa en la máquina y hace que sus direcciones lleguen a los bytes físicos correctos. La organización que ve el programa y la organización en el hardware son cosas distintas.
Por qué varios programas permanecen en memoria
Los primeros sistemas podían mantener un programa junto al sistema operativo. Por ejemplo, el sistema operativo podía ocupar los primeros 64 KB y el programa la memoria restante. La multiprogramación mantenía listo más de un proceso, de modo que la CPU podía trabajar mientras otro proceso esperaba una entrada o salida. El tiempo compartido cambiaba la CPU entre procesos con suficiente frecuencia para atender a usuarios interactivos.
Guardar en disco toda la memoria de un proceso en cada cambio haría que los cambios fueran demasiado lentos. Mantener varios procesos en la memoria física evita esa copia, pero crea un problema de protección. Una dirección generada por un proceso no debe permitirle sobrescribir el sistema operativo ni un proceso vecino.
Los tamaños de memoria aquí siguen la convención binaria usada en estos modelos: 1 KB son 1024 bytes, también expresados como 1 KiB; 1 MB son 1024 KB. Un espacio de direcciones de 16 KB tiene 16 384 ubicaciones de bytes, numeradas de 0 a 16 383. El número 16 384 es el límite final, no una dirección de byte válida.
Código, datos, montículo y pila
| Región | Qué contiene | Cómo se usa |
|---|---|---|
| Código | Instrucciones de máquina | La CPU busca instrucciones aquí. |
| Datos estáticos | Variables globales y variables locales estáticas | El almacenamiento dura toda la ejecución del programa. |
| Montículo | Bloques solicitados durante la ejecución | El programa solicita y libera bloques. |
| Pila | Estado de llamadas a funciones y variables locales ordinarias | Las llamadas crean marcos; los retornos los liberan. |
En una organización didáctica clásica de 16 KB, el código usa las direcciones bajas, desde 0 hasta el límite de 1 KB. El montículo comienza por encima del código y crece hacia arriba. La pila comienza en el límite superior y crece hacia abajo. El espacio libre entre ambos da a las dos regiones margen para crecer. Las organizaciones reales varían; por ejemplo, cada hilo tiene su propia pila. Las funciones de las regiones siguen siendo útiles incluso cuando cambian sus posiciones.
Sigue un puntero hasta la memoria correcta
Una dirección virtual identifica un byte en el espacio de direcciones de un proceso. Una dirección física identifica un byte en el hardware de memoria de la máquina. Cuando el código C imprime printf("%p", (void *) &x), imprime una dirección virtual. El puntero impreso no revela el byte físico que almacena x.
Supón que dos procesos usan ambos la dirección virtual 1000. Cada dirección se interpreta dentro del espacio de direcciones de su proceso, por lo que los accesos pueden llegar a bytes físicos diferentes. Del mismo modo, el código en la dirección virtual 0 no tiene por qué ocupar la dirección física 0. El sistema operativo puede colocarlo en otro lugar y configurar la traducción por hardware para acceder a él.
El procesador traduce las búsquedas de instrucciones, las cargas y los almacenamientos. El sistema operativo elige y gestiona las correspondencias, incluido el cambio de ubicaciones físicas mientras mantiene estables las direcciones virtuales del programa.
Puntos clave
- Un espacio de direcciones es la vista de la memoria de un proceso, no su ubicación física.
- El código, los datos estáticos, el montículo y la pila cumplen distintas funciones de almacenamiento.
- Las direcciones virtuales se interpretan dentro de un proceso; valores iguales pueden acceder a bytes físicos diferentes.
- Un espacio de direcciones de 16 KB tiene los bytes de 0 a 16 383 según la convención binaria para KB.
1.2 Transparencia, eficiencia y protección
Un sistema de memoria debe hacer más que traducir correctamente un número. Debe permitir que los programas ordinarios se ejecuten sin gestionar la ubicación física, mantener bajo el coste de la traducción y hacer cumplir los límites que permiten compartir la memoria de forma segura. Estos requisitos son la transparencia, la eficiencia y la protección.
Mantén la vista del programa
La transparencia significa que un programa se ejecuta como si tuviera memoria privada. Usa sus propias direcciones para el código y los datos sin tener que seguir qué otros procesos están presentes ni dónde se encuentran sus bytes. El sistema operativo y el hardware mantienen esta vista de forma transparente. Mover un proceso en la memoria física no debería exigir que el proceso reescriba sus punteros.
La ilusión no requiere una copia física distinta de cada byte para cada proceso. Por ejemplo, el código protegido de solo lectura puede compartirse. Lo que importa es que la compartición mantenga el comportamiento y los derechos de acceso que corresponden a cada proceso.
Ten en cuenta ambos tipos de coste
Cada búsqueda de instrucción, carga y almacenamiento necesita traducción. Ejecutar una rutina del sistema operativo para cada acceso haría que la ejecución ordinaria fuera demasiado lenta. El hardware realiza las operaciones frecuentes; el código del sistema operativo se ocupa de la configuración, los cambios y los fallos.
La eficiencia en espacio también importa. Un mecanismo de traducción pequeño y rápido puede aun así desperdiciar una cantidad considerable de memoria. Una sola región de base y límite reserva el espacio sin usar entre el montículo y la pila. La segmentación evita asignar memoria física a ese espacio, pero introduce regiones físicas de tamaño variable y huecos entre ellas. Los metadatos, el espacio reservado sin usar y los huecos afectan a la cantidad de trabajo útil que cabe en la memoria.
| Objetivo | Pregunta que debes hacerte |
|---|---|
| Transparencia | ¿Sigue el programa usando sus propias direcciones sin gestionar su ubicación? |
| Eficiencia en tiempo | ¿Cuánto trabajo añade cada acceso a memoria? |
| Eficiencia en espacio | ¿Cuánta memoria consumen los metadatos o el espacio inutilizable? |
| Protección | ¿Puede el proceso acceder solo a las regiones y operaciones que tiene permitidas? |
Detén un acceso no permitido en el límite
Sin protección, un puntero erróneo en un editor de texto podría sobrescribir otro proceso o el núcleo. El daño podría aparecer mucho más tarde en código sin relación aparente. Cuando se hacen cumplir los límites, el hardware rechaza un acceso fuera de la región permitida y genera una excepción. El sistema operativo gestiona la excepción y suele terminar el proceso defectuoso, normalmente comunicando un fallo de segmentación.
La protección aísla los procesos entre sí. No hace que el uso de la memoria en C sea seguro dentro de una región permitida del montículo. Una escritura que sobrepasa un bloque asignado puede alcanzar otro bloque del mismo proceso. Los límites de los procesos y los límites de los bloques del asignador son distintos.
Separa la operación de la decisión
Un mecanismo es la forma de realizar una operación. Sumar el valor de un registro base y comprobar un registro límite son mecanismos. Una política elige entre las acciones posibles: dónde colocar un proceso, qué hueco libre usar o cuándo mover un segmento.
Mantenerlos separados permite al sistema operativo cambiar su estrategia de colocación y conservar la misma traducción por hardware. La virtualización de memoria comienza con esta vista privada y protegida; no se define por el uso del disco como memoria adicional.
Puntos clave
- La transparencia mantiene la vista del programa cuando cambia su ubicación física.
- La eficiencia en tiempo importa en cada acceso a memoria; la eficiencia en espacio incluye las regiones sin usar y los metadatos.
- La protección aísla los procesos, pero no hace cumplir todos los límites de los bloques del montículo.
- Los mecanismos realizan operaciones; las políticas eligen entre alternativas.
- El hardware traduce los accesos ordinarios; el sistema operativo gestiona la traducción y atiende los fallos.
2De las asignaciones en C a las regiones del sistema operativo
Una solicitud de memoria del montículo atraviesa dos niveles de gestión de memoria. La biblioteca C encuentra un bloque para el programa, mientras que el sistema operativo proporciona y protege las regiones de las que se extraen los bloques. Seguir estos niveles explica por qué una variable puntero y el bloque que apunta tienen tiempos de vida distintos, por qué liberar un bloque puede dejar sin cambios el uso de memoria del proceso y por qué una compilación correcta dice poco sobre la validez de los accesos posteriores al montículo.
2.1 Solicita bloques y respeta sus tiempos de vida
Una variable puntero y la memoria a la que apunta son objetos separados. Comprender sus tiempos de vida es el punto de partida para la API de memoria de C. Las variables locales ordinarias suelen usar almacenamiento automático en la pila, los bloques del montículo duran hasta que se liberan y las variables globales y locales static tienen almacenamiento durante toda la ejecución del programa.
Sigue la asignación, no solo el puntero
void f(void) {
int x;
int *p = malloc(sizeof(int));
}
En la organización habitual de la pila, x y p pertenecen a esta llamada a f. El entero solicitado pertenece al montículo. El retorno elimina la variable puntero local, pero no libera el bloque del montículo. Si no queda ninguna copia de la dirección, el programa ha perdido el acceso a un bloque asignado vigente: una fuga de memoria.
malloc(size) solicita al menos esa cantidad de bytes y devuelve un puntero, o NULL cuando no puede atender la solicitud. Sus bytes no están inicializados para el programa. Para 10 enteros, usa malloc(10 * sizeof(int)); donde un entero ocupa 4 bytes, eso solicita 40 bytes. Para una cadena, reserva espacio para sus caracteres más un byte para el carácter nulo de terminación: malloc(strlen(s) + 1).
sizeof(a) mide el objeto llamado a. Si a es un puntero, da el tamaño del puntero, no el de la asignación. Un puntero de 8 bytes puede referirse a un bloque de 40 bytes.
Conoce qué hace cada operación de la biblioteca
| Llamada | Propósito principal |
|---|---|
malloc | Obtener un bloque cuyos bytes no se ponen a cero. |
calloc | Obtener un bloque lleno de bytes de valor cero. |
realloc | Cambiar el tamaño de un bloque y posiblemente moverlo. |
free | Devolver un bloque asignado al asignador. |
free recibe el puntero devuelto, sin un argumento de tamaño. El asignador conserva metadatos de tamaño, normalmente en una cabecera antes del bloque. Pasa el puntero devuelto para un bloque actualmente asignado; un puntero al interior del bloque no es un sustituto válido. free(NULL) es válido y no hace nada. Estas funciones son rutinas de la biblioteca C, no llamadas al sistema.
Reconoce el error por el tiempo de vida o el límite
Un puntero sin una asignación válida no puede usarse como si ya apuntara a un espacio de almacenamiento. Leer bytes recién asignados antes de inicializarlos es una lectura de memoria sin inicializar. Escribir más allá del final asignado es un desbordamiento de búfer; omitir el byte de terminación de una cadena puede causarlo.
Después de free, los punteros antiguos al bloque quedan colgantes. Acceder mediante uno de ellos es un uso después de la liberación. Liberar el bloque de nuevo es una doble liberación de memoria. Liberar una dirección que el asignador no devolvió para un bloque vigente es una liberación no válida. Perder un bloque por una fuga es distinto: el bloque permanece asignado, pero el programa deja de liberarlo cuando debería.
Comprende qué puede comprobar el hardware
La compilación puede tener éxito pese a todos estos errores. El hardware suele comprobar las regiones y los permisos del proceso, no cada asignación de la biblioteca. Cruzar el límite de un bloque mientras se permanece dentro del montículo permitido del proceso puede tener un comportamiento indefinido sin provocar un fallo inmediato. El programa puede corromper datos, fallar más tarde, leer valores sin sentido o parecer que funciona. Valgrind y AddressSanitizer pueden detectar muchos de estos errores durante la ejecución.
Puntos clave
- El tiempo de vida de un bloque del montículo es independiente del de la variable puntero.
- Usa
sizeofpara el tipo almacenado;sizeofaplicado a un puntero no mide su bloque. malloc,calloc,reallocyfreeson rutinas de biblioteca.- Una asignación para una cadena necesita espacio para su byte nulo de terminación.
free(NULL)no hace nada; un puntero al interior de un bloque no es un puntero válido al bloque asignado.- Las comprobaciones de regiones del hardware pueden pasar por alto errores de memoria a nivel de bloque dentro del montículo.
2.2 Cómo obtiene memoria el asignador
La biblioteca C y el sistema operativo gestionan la memoria a distintas escalas. El sistema operativo establece regiones en el espacio de direcciones de un proceso y les proporciona memoria física. El asignador divide la memoria disponible del montículo en bloques, registra los bloques libres y los reutiliza entre llamadas.
Mueve el límite del montículo
El límite del montículo es la dirección situada justo después del final del montículo tradicional. brk establece ese límite en una dirección elegida. sbrk(n) lo desplaza un incremento de bytes y, si tiene éxito, devuelve el límite anterior. sbrk(0) indica el límite actual sin moverlo.
Supón que el límite es 40 960 y que el asignador llama correctamente a sbrk(8192). El valor devuelto es 40 960. El nuevo límite es:
Los bytes añadidos ocupan las direcciones virtuales de 40 960 a 49 151. El nuevo límite, 49 152, está justo después de la región añadida. Confundir el valor devuelto con el nuevo límite desplaza todos los cálculos posteriores de colocación.
Las aplicaciones usan la biblioteca de asignación en lugar de mover el límite directamente. La biblioteca lleva el registro de las partes de su región que le pertenecen. Los cambios independientes en ese límite pueden invalidar sus registros.
Obtén un mapeo separado
mmap puede crear una región anónima: memoria no asociada a un archivo, inicialmente llena de bytes de valor cero. munmap elimina un mapeo. Un asignador puede usar mapeos separados para asignaciones grandes y devolver esos mapeos al sistema operativo cuando se liberan.
En glibc, el umbral inicial predeterminado para esta vía es de 128 KB, o 131 072 bytes, y puede aumentar. Una asignación suficientemente grande suele mapearse por separado si no puede atenderse con el espacio libre existente. Esta es una política de la biblioteca, no un límite universal del lenguaje C.
Libera a nivel de biblioteca o de sistema operativo
| Suceso | Qué cambia |
|---|---|
| Liberar un bloque pequeño reutilizable | El asignador puede atender otra solicitud con él. |
| Eliminar un mapeo separado | La región mapeada deja de pertenecer al proceso. |
| Terminar el proceso | El sistema operativo recupera la memoria del proceso. |
Una llamada a free suele devolver un bloque pequeño a la reserva de la biblioteca. Por ello, el proceso puede mostrar después la misma ocupación de memoria. La memoria está disponible para reutilizarse sin otra solicitud al sistema operativo.
La terminación del proceso recupera incluso las asignaciones que el programa perdió por fugas. Sin embargo, durante la vida de un servidor de larga duración, las fugas repetidas siguen consumiendo su memoria disponible. Recuperar la memoria al terminar no evita esa presión mientras se ejecuta.
Relaciona el crecimiento del montículo con la traducción
En el modelo de segmentación, el montículo es un segmento físico contiguo. Ampliarlo requiere bytes físicos libres justo encima de él. Si esos bytes están ocupados, el sistema operativo puede mover el segmento a un hueco mayor y actualizar su estado de traducción. Si no hay una región adecuada disponible, la ampliación falla. Si el asignador no puede obtener suficiente espacio, malloc devuelve NULL.
Puntos clave
- El sistema operativo proporciona regiones; la biblioteca las divide en bloques.
- Una llamada a
sbrkque tiene éxito devuelve el límite anterior, no el nuevo. mmapanónimo obtiene una región separada llena de ceros;munmapla elimina.- Liberar un bloque suele permitir su reutilización sin reducir la memoria del proceso asignada por el sistema operativo.
- Un montículo segmentado necesita espacio físico contiguo para crecer.
3Traducción mediante base y límite
Base y límite convierte una dirección relativa a un proceso en una dirección física mediante una comparación y una suma. Su sencillez facilita ver el reparto del trabajo: el hardware comprueba cada acceso, mientras que el sistema operativo elige una ranura, restaura el estado de traducción al cambiar de proceso y gestiona los fallos. Seguir un proceso a través de estos eventos también revela el coste principal: incluso las direcciones sin usar entre el montículo y la pila ocupan parte de su ranura física.
3.1 Comprobación y traducción de una dirección
La reubicación dinámica traduce direcciones mientras se ejecuta un programa. En el modelo de base y límite, un proceso ocupa una región física contigua. Comienza con espacios de direcciones del mismo tamaño que caben en la memoria física; un par de registros describe entonces la región del proceso que se ejecuta en ese momento.
Comprueba primero la dirección virtual
El registro base contiene la dirección física del primer byte de la región. El registro límite contiene el tamaño de la región en bytes. Para una dirección virtual no negativa, la regla es:
Si se supera la comprobación:
De lo contrario, el hardware genera una excepción. Un tamaño es una cantidad, por lo que la dirección igual al límite ya está fuera de la región. Las direcciones virtuales negativas también son inválidas.
Recorre los límites de bytes
Considera un espacio de direcciones de 8 KB con base 20 480 y límite 8192. Sus bytes virtuales van de 0 a 8191. La dirección virtual 1000 supera la comprobación y accede al byte físico 21 480. El último byte virtual permitido, 8191, accede a 28 671. La dirección 9000 falla porque es al menos 8192; el hardware debe rechazarla antes de realizar el acceso físico.
Las búsquedas de instrucciones usan la misma traducción que los datos. Si una instrucción en la dirección virtual 128 carga desde la dirección virtual 3000, la búsqueda accede a la dirección física 20 608 y la carga accede a 23 480. Son dos accesos a memoria con dos direcciones traducidas, no una única traducción compartida para toda la instrucción.
Distingue las convenciones del límite
| El registro límite contiene | Qué se compara |
|---|---|
| Tamaño de la región | La dirección virtual debe ser menor que el tamaño. |
| Límite físico final | La dirección traducida debe ser menor que ese límite. |
La misma región de 8 KB tiene el límite físico final 28 672. Ambas convenciones permiten exactamente los bytes de 20 480 a 28 671. Comparar la dirección física 21 480 con el tamaño 8192 mezcla las dos convenciones y rechaza incorrectamente un acceso permitido.
Mueve la memoria sin cambiar los punteros
La MMU, o unidad de gestión de memoria, realiza las comprobaciones y la suma. El sistema operativo puede pausar un proceso, copiar su región a otro lugar y cambiar la base. El proceso sigue usando las mismas direcciones virtuales, por eso la reubicación es dinámica.
En la reubicación estática, en cambio, un cargador reescribe las direcciones incorporadas al cargar el código. Reescribir una referencia de 1000 a 21 480 registra una ubicación física en el programa. Moverlo más tarde requiere nuevas reescrituras, y la reescritura por sí sola no impide que un programa construya una dirección fuera de su región.
Suma la base solo a una dirección virtual. Sumarla a una dirección física ya traducida desplaza la ubicación por segunda vez y destruye la correspondencia.
Puntos clave
- Cuando el límite es un tamaño, comprueba la dirección virtual antes de sumar la base.
- El intervalo permitido excluye la dirección igual al límite.
- Tanto las búsquedas de instrucciones como los accesos a datos se traducen.
- Un límite físico final y un límite expresado como tamaño en bytes usan comparaciones distintas.
- La reubicación dinámica cambia la ubicación sin reescribir los punteros virtuales.
3.2 Instalación y cambio del estado de traducción
El hardware mantiene los registros de traducción del proceso que se ejecuta en una CPU. El sistema operativo conserva el estado guardado de los procesos que esperan. La protección depende de que solo el código privilegiado del sistema operativo tenga capacidad para cambiar ese estado.
Proporciona las operaciones de hardware
La CPU necesita los modos usuario y núcleo, un par de base y límite en su MMU y circuitos para la comprobación y la suma. También necesita operaciones privilegiadas para cambiar el par e instalar manejadores de excepciones. Las direcciones no permitidas y los intentos de ejecutar instrucciones privilegiadas en modo usuario deben generar excepciones.
Si un programa de usuario pudiera cambiar su base, podría redirigir sus direcciones al núcleo o a otro proceso. Las comprobaciones de límite protegerían entonces la región equivocada. Restringir las actualizaciones forma parte, por tanto, del mecanismo de protección, no es solo una comodidad administrativa.
Crea y ejecuta un proceso
Durante el arranque, el sistema operativo instala sus manejadores de trampas y excepciones, inicia el temporizador de interrupciones y prepara sus registros de memoria libre. Cuando comienza un proceso, el sistema operativo encuentra una ranura física para su espacio de direcciones. Con ranuras de igual tamaño, una lista de bloques libres puede simplemente registrar cuáles están sin usar.
El sistema operativo marca la ranura elegida como ocupada, registra la base y el límite del proceso, carga los registros y entra en modo usuario. El proceso se ejecuta entonces directamente en la CPU. El hardware traduce los accesos ordinarios sin llamar al sistema operativo por cada byte.
Restaura el par correcto en un cambio de contexto
Una interrupción del temporizador transfiere el control al sistema operativo. Este guarda los registros del proceso anterior, incluidos la base y el límite, en su bloque de control de proceso y después restaura los valores del siguiente proceso antes de volver al modo usuario.
Supón que la base de A es 20 480 y la de B es 40 960, ambas con límite 8192. La dirección virtual 1000 de A accede a 21 480. Después de cambiar a B, el mismo número virtual accede a 41 960. Restaurar los registros de la CPU sin restaurar el estado de traducción haría que B accediera a la región de A usando los punteros de B.
La CPU tiene el par activo; cada proceso tiene su propio par guardado. No imagines un único par permanente para toda la máquina ni supongas que los pares de todos los procesos están activos simultáneamente en una CPU.
Mueve, gestiona fallos y termina
Para mover A a la dirección física 49 152, el sistema operativo retira A de la ejecución, copia su región de 8 KB y actualiza la base guardada de A. Una vez que A se reanuda con esa base instalada, la dirección virtual 1000 accede a 50 152. Sus valores de puntero virtual no necesitan cambios.
Ante un acceso no válido, el hardware genera una excepción y transfiere la ejecución al modo núcleo en el manejador registrado. El sistema operativo suele terminar el proceso que causó el acceso. Al terminar, devuelve la ranura a la lista de bloques libres y libera los registros del proceso.
Puntos clave
- Solo el código privilegiado puede cambiar los registros de traducción.
- La CPU mantiene el estado activo; los bloques de control de proceso mantienen el estado guardado.
- Un cambio de contexto debe restaurar la base y el límite junto con los demás registros.
- La reubicación requiere pausar, copiar y actualizar la base guardada.
- El hardware genera excepciones de acceso; el sistema operativo las gestiona.
- La terminación devuelve la ranura física a la lista de bloques libres.
3.3 Por qué una ranura sencilla desperdicia memoria
Base y límite cumple dos objetivos con poco coste: la traducción es transparente y cada dirección se comprueba frente a la región asignada. Su principal debilidad es la relación entre esa región y los bytes que el proceso usa realmente.
Reserva toda la extensión
El hardware solo necesita una suma y una comparación en la ruta frecuente. Un asignador de ranuras de tamaño fijo también puede elegir rápidamente una ranura libre. Ninguna de estas ventajas significa que la ranura esté llena de datos útiles.
En la organización clásica, el código y el montículo están cerca de un extremo y la pila cerca del otro. Un par de base y límite traduce todo el intervalo. El espacio sin usar entre el montículo y la pila ocupa memoria física igual que las partes útiles.
Para un espacio de direcciones de 16 KB que usa 1 KB de código, 2 KB de montículo y 1 KB de pila:
El desperdicio es fragmentación interna: bytes sin usar dentro de una región ya asignada a un proceso. No se debe a que el asignador del montículo elija mal un bloque. Incluso un montículo de 2 KB perfectamente aprovechado deja reservado el gran espacio intermedio.
Distingue tres cuestiones de tamaño
La extensión del espacio de direcciones, los bytes usados actualmente y la memoria física disponible son cantidades distintas. Un espacio de 32 bits direccionado por bytes abarca bytes, o 4 GB. Reservarlo como un solo bloque físico requiere los 4 GB completos aunque el proceso solo use actualmente unos pocos megabytes.
| Restricción | Consecuencia |
|---|---|
| Una región contigua | Los huecos libres separados no pueden contener una única región de proceso. |
| Ranuras de igual tamaño | Los procesos pequeños desperdician espacio; los más grandes pueden no caber. |
| Un espacio de direcciones disperso | Los huecos virtuales sin usar siguen consumiendo memoria física reservada. |
Hacer que las ranuras tengan tamaños variables elimina la restricción de igual tamaño, pero no elimina la necesidad de un hueco contiguo. También crea un problema de colocación: el sistema operativo debe elegir entre huecos libres de distintos tamaños. Reducir una ranura no puede mantener tanto las direcciones bajas del código como una dirección alta y distante de la pila si toda la extensión debe seguir siendo válida en el mismo mapeo sencillo.
Reubica las regiones por separado
El código, el montículo y la pila no tienen que ser vecinos en la memoria física para mantener la vista del programa. Dar a cada uno su propia base y límite permite al sistema operativo asignar solo sus extensiones usadas y dejar el espacio virtual sin memoria física asignada. Esto es la segmentación, la generalización de un par de reubicación a varias regiones lógicas.
Para la organización de 16 KB anterior, las tres regiones usadas solo necesitan 4 KB en total antes de su propia sobrecarga de gestión. El ahorro de espacio procede de cambiar lo que se reubica como una unidad, no de hacer más rápida la suma del registro base.
Puntos clave
- Toda la extensión virtual ocupa una ranura física contigua.
- El espacio sin usar dentro de esa ranura es fragmentación interna.
- Las ranuras de igual tamaño limitan a los procesos grandes y desperdician espacio para los pequeños.
- La segmentación ahorra espacio al reubicar de forma independiente las regiones usadas.
4Traducción con segmentos separados
Un solo par de traducción reserva los espacios vacíos dentro de un espacio de direcciones. La segmentación da al código, al montículo y a la pila ubicaciones físicas independientes, de modo que solo sus extensiones actuales necesitan memoria física. Traducir una dirección incluye ahora encontrar el segmento y su desplazamiento, con un cambio de signo adicional para la pila que crece hacia abajo. La flexibilidad resultante permite la protección y la compartición de código, a la vez que exige al sistema operativo encontrar huecos contiguos para regiones de distintos tamaños.
4.1 Una traducción propia para cada región
Un segmento es una región contigua de un espacio de direcciones con un propósito. En el modelo clásico, el código, el montículo y la pila reciben cada uno un par de base y tamaño. Sus regiones físicas pueden colocarse de forma independiente aunque el proceso conserve su organización virtual habitual.
Asigna memoria física solo a las extensiones usadas
Usa un espacio de direcciones de 16 KB con las siguientes ubicaciones. Los tamaños usan KB binarios, o KiB.
| Segmento | Extensión virtual | Base física o límite superior | Tamaño |
|---|---|---|---|
| Código | De 0 a 2047 | Base 40 960 | 2048 bytes |
| Montículo | De 4096 a 7167 | Base 26 624 | 3072 bytes |
| Pila | De 14 336 a 16 383 | Límite superior 53 248 | 2048 bytes |
El código y el montículo crecen hacia direcciones mayores; la traducción de la pila usa su límite superior y un desplazamiento negativo. Las tres regiones físicas usan solo 7 KB en total. Los huecos virtuales entre ellas no necesitan almacenamiento físico. Cada segmento sigue siendo contiguo; lo que ya no requiere adyacencia es la relación entre segmentos.
Traduce un segmento que crece hacia arriba
Primero identifica el segmento. Después calcula el desplazamiento desde su comienzo virtual. Comprueba que el desplazamiento no sea negativo y que sea menor que su tamaño actual; luego súmalo a la base física:
Para la dirección virtual 500, el desplazamiento dentro del código es 500. Es menor que 2048, por lo que el acceso llega a la dirección física 41 460.
Para la dirección virtual 5000, el desplazamiento dentro del montículo es:
La comprobación del tamaño se supera porque 904 es menor que 3072. El resultado es:
Sumar la dirección virtual completa a la base del montículo produciría 31 624. Eso incorpora por error la posición inicial virtual del montículo a un cálculo que solo necesita la distancia dentro del segmento.
Comprueba el segmento, no solo la extensión del espacio de direcciones
La dirección virtual 7500 cabe en 14 bits, pero eso no significa que esté permitida. Su desplazamiento dentro del montículo es 3404, fuera de la extensión actual de 3072 bytes. El hardware genera una excepción. Una dirección puede estar, por tanto, dentro de la extensión total del espacio de direcciones y aun así fuera de todas las regiones válidas.
El término fallo de segmentación se originó con los accesos segmentados no válidos y sigue usándose para accesos no permitidos en sistemas con otros esquemas de traducción. El nombre del error por sí solo no identifica el mecanismo de traducción de la máquina.
Puntos clave
- Cada segmento tiene su propia base y tamaño.
- El desplazamiento de un segmento que crece hacia arriba se mide desde el comienzo virtual de ese segmento.
- Suma a la base física solo el desplazamiento comprobado.
- Una dirección dentro de la extensión virtual total puede aun así provocar un fallo.
- Los huecos virtuales sin usar entre segmentos no requieren memoria física.
4.2 Selección del segmento y extracción de su desplazamiento
Antes de que el hardware pueda usar la base y el tamaño de un segmento, debe decidir a qué segmento se refiere un acceso. Un diseño explícito sitúa esa elección en bits de la dirección. Un diseño implícito la deduce de la forma en que la CPU creó la dirección.
Divide una dirección de 14 bits
Asigna los dos bits superiores al número de segmento y los doce bits inferiores al desplazamiento. El campo de dos bits tiene cuatro valores posibles. Usa 00 para código, 01 para montículo y 11 para pila; deja 10 sin usar.
El campo de desplazamiento puede representar 4096 valores distintos, de 0 a 4095. Por tanto, la ventana virtual máxima de cada segmento es de 4 KB, incluso cuando la extensión válida actual del segmento es menor. La capacidad máxima y el tamaño actual son límites distintos.
Para la dirección virtual 5000, la representación de 14 bits es:
01 0011 1000 1000
El 01 inicial selecciona el montículo. El 0011 1000 1000 restante es 904 en decimal. Con un tamaño de montículo de 3072 y una base física de 26 624, el desplazamiento supera la comprobación de tamaño y llega a la dirección física 27 528.
Usa una máscara y un desplazamiento de bits
La misma división puede expresarse como código:
segment = (va & 0x3000) >> 12;
offset = va & 0x0FFF;
La máscara 0x3000 conserva los dos bits selectores; desplazarlos doce posiciones los mueve a las posiciones inferiores para obtener el número de segmento. La máscara 0x0FFF pone a cero esos bits selectores y conserva el desplazamiento. Para va = 0x1388, los resultados son el segmento 1 y el desplazamiento 0x388, o 904.
No sumes 0x1388 directamente a la base del montículo. Ese valor incluye tanto el selector de segmento como el desplazamiento. El selector elige los registros; solo el desplazamiento interviene en la traducción dentro del segmento. La dirección física resultante no necesita conservar el patrón de bits del selector.
Reconoce el coste de la división
Un selector de dos bits crea cuatro ventanas. Dejar 10 sin usar hace que una cuarta parte de la extensión virtual de 16 KB no esté disponible. Ningún segmento puede crecer más allá de su ventana de 4 KB solo porque quede libre más memoria física. Otros diseños pueden usar una división distinta; combinar el código y el montículo en un segmento permite que un solo bit selector lo distinga de la pila.
Deja que el tipo de acceso elija
En un diseño implícito, las búsquedas de instrucciones usan el segmento de código porque su dirección procede del contador de programa. Las referencias basadas en el puntero de pila o en el puntero de marco usan el segmento de pila. Los demás accesos usan el segmento de montículo en este modelo simplificado.
| Método de selección | De dónde procede la elección |
|---|---|
| Explícito | Un campo de segmento dentro de la dirección virtual |
| Implícito | El registro o tipo de acceso que formó la dirección |
Puntos clave
- Los bits selectores eligen el estado de traducción; los bits de desplazamiento localizan un byte dentro de la ventana.
- Doce bits de desplazamiento permiten una ventana máxima de segmento de 4096 bytes.
- La aplicación de una máscara y el desplazamiento de bits separan los campos sin incorporar los bits selectores a la suma de la base.
- La selección implícita usa el origen de una dirección, como el contador de programa o el puntero de pila.
4.3 Traducción de la pila y aplicación de permisos
La pila crece hacia direcciones menores. Su traducción necesita un bit de dirección de crecimiento además de una base y un tamaño. En este modelo, 1 indica crecimiento hacia arriba y 0 crecimiento hacia abajo. Los permisos de acceso añaden otra comprobación independiente: un byte puede estar dentro de los límites y aun así no permitir la operación solicitada.
Trata la base de la pila como un límite superior
En un segmento que crece hacia arriba, la base identifica su primer byte físico. En un segmento que crece hacia abajo, la base identifica el límite situado justo después de su byte físico de dirección más alta. En la organización del ejemplo, una base de pila de 53 248 y un tamaño de 2048 abarcan los bytes físicos de 51 200 a 53 247.
Para la ventana de pila de 4 KB seleccionada por 11, convierte el campo de desplazamiento de doce bits en un desplazamiento negativo:
El campo va de 0 a 4095, por lo que este desplazamiento siempre es negativo. Es válido cuando su magnitud no supera el tamaño actual de la pila. Después suma el desplazamiento con signo a la base.
Resuelve un acceso permitido a la pila
La dirección virtual 15 500 selecciona la pila. Su ventana comienza en la dirección virtual 12 288, por lo que su campo de desplazamiento es 3212. Convierte el campo:
La profundidad 884 está dentro del tamaño 2048. La traducción da:
Sumar el valor positivo 3212 a la base apuntaría por encima de la pila. El campo todavía no es el desplazamiento necesario para un segmento que crece hacia abajo.
La dirección virtual 13 000 da, en cambio, el campo 712 y el desplazamiento −3384. Su profundidad supera 2048, por lo que el hardware genera un fallo. Si el sistema operativo amplía la pila correctamente, el aumento de su tamaño puede hacer que más direcciones bajas sean válidas.
Incluye el extremo inferior
Un desplazamiento de −2048 llega al byte de dirección más baja de la pila, 51 200, y está permitido. Un desplazamiento de −2049 queda fuera. La comprobación para crecimiento hacia abajo incluye, por tanto, la magnitud igual al tamaño. Esto coincide con el número de bytes de la regla para crecimiento hacia arriba, aunque esa regla excluye un desplazamiento igual al tamaño: la base para crecimiento hacia arriba es un byte, mientras que la base para crecimiento hacia abajo es un límite final.
Comprueba la operación solicitada
Los bits de protección registran los permisos de lectura, escritura y ejecución. El código suele ser de lectura y ejecución; el montículo y la pila suelen ser de lectura y escritura. Una escritura en código de lectura y ejecución provoca un fallo incluso cuando su desplazamiento es válido. Ejecutar datos también provoca un fallo cuando no hay permiso de ejecución.
El código de solo lectura puede compartirse. El sistema operativo puede hacer que los segmentos de código de dos procesos apunten a la misma región física y denegar la escritura en ambos. Los bytes de instrucciones ocupan una sola copia física, mientras cada proceso conserva un montículo y una pila separados.
Puntos clave
- La base de un segmento que crece hacia abajo marca su límite superior, no un byte almacenado.
- Resta el tamaño máximo de la ventana al campo de desplazamiento para obtener el desplazamiento negativo.
- El byte de dirección más baja de la pila está permitido cuando la magnitud del desplazamiento es igual al tamaño actual.
- Tanto los límites como la operación solicitada deben superar las comprobaciones del hardware.
- Compartir código de solo lectura ahorra memoria física mientras las regiones privadas de escritura permanecen separadas.
4.4 Gestión de segmentos físicos de tamaño variable
La segmentación sustituye una región grande por varias más pequeñas. Esto evita asignar memoria física a los huecos virtuales vacíos, pero ahora el sistema operativo debe colocar y ampliar regiones de distintos tamaños mientras conserva el estado de traducción de cada proceso.
Guarda todas las partes del mapeo
En un cambio de contexto, la base y el tamaño ya no bastan. El sistema operativo guarda y restaura la base, el tamaño, la dirección de crecimiento y los permisos de cada segmento. Restaurar una pila con la dirección equivocada o código con permisos incorrectos cambiaría el significado de direcciones por lo demás idénticas.
Cuando un asignador necesita más espacio de montículo, el sistema operativo debe ampliar el segmento físico del montículo. Los bytes libres situados justo encima permiten el crecimiento directo. De lo contrario, el sistema operativo puede moverlo a un hueco mayor adecuado y actualizar su base. Si no puede obtener una región adecuada, la ampliación falla.
Elige la granularidad
| Esquema | Organización | Consecuencia para la gestión |
|---|---|---|
| Segmentación de grano grueso | Unas pocas regiones, como código, montículo y pila | Un pequeño conjunto de registros de segmento describe el proceso. |
| Segmentación de grano fino | Muchas regiones, quizá una por estructura de datos | Una tabla de segmentos en memoria permite más opciones de compartición y protección. |
Multics usaba segmentación de grano fino. Más segmentos permiten unidades de control más pequeñas, pero requieren más metadatos de traducción y gestión.
Encuentra un hueco suficientemente grande
Los segmentos físicos de tamaño variable dejan huecos libres de distintos tamaños cuando los procesos comienzan, crecen y terminan. La fragmentación externa ocurre cuando hay suficientes bytes libres en total, pero ningún hueco por sí solo puede contener el segmento solicitado.
Supón que los huecos libres son de 8 KB, 6 KB y 10 KB. Su total es 24 KB. Un segmento de montículo de 12 KB sigue sin caber: el hueco disponible más grande es de solo 10 KB. Unir los huecos sobre el papel no hace que sus direcciones físicas sean adyacentes.
La compactación puede corregir esta organización. El sistema operativo pausa los procesos, copia los segmentos uno junto a otro y actualiza sus bases. Las direcciones virtuales siguen funcionando porque la traducción oculta los movimientos físicos. El resultado es una región libre grande y contigua, pero la copia es costosa y las nuevas asignaciones pueden volver a fragmentar la memoria.
Las políticas de colocación, como el primer ajuste y el mejor ajuste, intentan limitar los sobrantes inadecuados sin copiar. Ninguna política de colocación de tamaños variables elimina la fragmentación externa para todas las secuencias de solicitudes. Un único segmento grande también puede desperdiciar espacio dentro de su propia extensión cuando solo se usan partes dispersas.
Reconoce el modelo en los sistemas modernos
La paginación divide la memoria en piezas de tamaño fijo y evita exigir que cada región lógica ocupe un solo hueco físico. El modelo de segmentación sigue siendo útil para comprender las regiones, la protección y la compartición. En el modo de 64 bits de x86-64, las bases ordinarias de segmentación de código, datos y pila actúan como cero y sus límites no se comprueban; FS y GS conservan bases útiles para datos por hilo o por CPU. Un mensaje de acceso no permitido llamado fallo de segmentación no significa que el modelo clásico de tres segmentos esté activo.
Puntos clave
- Los cambios de contexto restauran la dirección de crecimiento y los permisos, además de las bases y los tamaños.
- La segmentación de grano fino proporciona más regiones independientes mediante una tabla de segmentos.
- La fragmentación externa depende del tamaño de cada hueco, no solo del total.
- La compactación mueve segmentos físicos y actualiza las bases, conservando los punteros virtuales.
- Las políticas de colocación reducen la fragmentación sin garantizar su eliminación.
- La traducción ordinaria de x86-64 difiere de la segmentación clásica.
5Gestión de bloques libres y sus costes
Un asignador debe saber qué bytes están libres y elegir un bloque que pueda contener cada solicitud. La división y la fusión cambian la lista de bloques libres; las políticas de colocación determinan qué huecos quedan para solicitudes posteriores. Las cabeceras, la alineación y el redondeo a potencias de dos añaden sus propios costes. Seguir estos cambios permite explicar fallos de asignación, comparar políticas y ver por qué las cachés especializadas y la asignación por bloques compañeros intercambian flexibilidad por velocidad.
5.1 Localización del desperdicio dentro de los bloques o entre ellos
La gestión del espacio libre registra la memoria disponible y elige dónde colocar cada solicitud. Las solicitudes de igual tamaño pueden usar una lista de bloques intercambiables. Los tamaños variables son más difíciles: tanto un asignador del montículo como un sistema operativo que coloca segmentos deben encontrar un bloque contiguo suficientemente grande para la siguiente solicitud.
Localiza la fragmentación externa
Considera una región de 60 bytes con los bytes 0–19 libres, un bloque asignado en 20–39 y los bytes 40–59 libres. Hay cuarenta bytes libres, pero ninguno de los huecos libres puede contener una solicitud de 25 bytes. El bloque vigente del medio impide tratar esos huecos como una sola región.
Esto es fragmentación externa: hay capacidad libre fuera de los bloques asignados, pero su disposición la hace inutilizable para una solicitud contigua concreta. Los bytes libres no han desaparecido. Aún pueden atender solicitudes más pequeñas o resultar útiles cuando se liberan los bloques intermedios.
Localiza la fragmentación interna
Un asignador que redondea las solicitudes a múltiplos de 16 entrega un bloque de 32 bytes para una solicitud de 20 bytes. Los 12 bytes adicionales están dentro de una asignación ya entregada. Ese desperdicio es fragmentación interna.
El espacio sin usar entre el montículo y la pila en una ranura de base y límite es otro ejemplo. La asignación por bloques compañeros introduce el mismo tipo de desperdicio al redondear a potencias de dos. El nivel de gestión es distinto, pero la ubicación del espacio sin usar es la característica que lo define.
| Desperdicio | Dónde se encuentra | Qué lo hace costoso |
|---|---|---|
| Fragmentación interna | Dentro de una región asignada | Los bytes reservados superan el contenido útil. |
| Fragmentación externa | En huecos libres separados | Ningún hueco individual se ajusta a la extensión solicitada. |
Un mismo asignador puede sufrir ambas. Redondear una solicitud puede desperdiciar bytes dentro de su bloque mientras otros bloques libres permanecen separados en otra parte.
Fusiona vecinos libres sin mover datos vigentes
La fusión de bloques libres adyacentes une bloques libres físicamente adyacentes. Si se libera el bloque del medio de la región de 60 bytes, las tres partes pueden unirse en un hueco de 60 bytes. Si el bloque del medio sigue asignado, la fusión no puede atravesarlo. La fusión reduce la fragmentación externa, pero no garantiza un hueco suficientemente grande para cada solicitud.
Añadir más memoria a un montículo puede aliviar la presión, pero no cambia las direcciones de los bloques vigentes. Su colocación aún puede dejar pequeños huecos inutilizables.
Explica por qué el sistema operativo puede compactar segmentos
El sistema operativo puede copiar segmentos físicos y actualizar sus bases. Los programas conservan las direcciones virtuales, por lo que el mapeo puede ocultar esos movimientos. Un asignador general del montículo de C carece de una capa de traducción entre los punteros devueltos y las ubicaciones dentro del montículo. Un programa puede haber copiado un puntero en muchos objetos y el asignador no puede descubrir ni reescribir cada copia.
Mover un bloque vigente del montículo por sí solo dejaría esos punteros apuntando a su ubicación anterior. Por ello, la gestión ordinaria de malloc mantiene los bloques vigentes en las direcciones devueltas hasta que se liberan. Debe gestionar la fragmentación mediante la colocación, la reutilización, la división y la fusión del espacio libre.
Puntos clave
- El desperdicio interno está dentro de las asignaciones; la fragmentación externa está en huecos libres separados.
- La capacidad libre total no demuestra que quepa una solicitud contigua.
- La fusión une bloques libres adyacentes sin mover bloques vigentes.
- La reubicación de segmentos del sistema operativo puede conservar los punteros mediante traducción; la compactación ordinaria del montículo de C no puede hacerlo.
5.2 Seguimiento de cabeceras, divisiones y fusiones
Una lista de bloques libres registra los bloques libres por dirección y tamaño. La asignación divide un bloque o lo elimina de la lista; la liberación devuelve un bloque y puede fusionarlo con sus vecinos. La convención de tamaño importa: un tamaño registrado puede indicar la carga útil utilizable o el bloque completo con sus metadatos.
Divide y fusiona intervalos sencillos
Ignora primero las cabeceras. En una región de 60 bytes con entradas libres (0, 20) y (40, 20), una solicitud de 8 bytes colocada al comienzo devuelve la dirección 0. Las entradas restantes son (8, 12) y (40, 20).
Partiendo de nuevo de la organización original, libera los bytes asignados del medio, 20–39. Sin fusión, tres entradas de 20 bytes siguen sin poder atender individualmente una solicitud de 30 bytes. Fusionar los intervalos adyacentes produce (0, 60), que sí puede atenderla. El orden por dirección ayuda al asignador a reconocer los vecinos; la adyacencia en la lista por sí sola no basta si sus intervalos físicos no se tocan.
Recupera la cabecera a partir del puntero del usuario
free(ptr) no recibe un tamaño. Un asignador sencillo guarda una cabecera de tamaño justo antes de la carga útil, a veces con un valor de comprobación o número mágico. Restar la longitud de la cabecera permite encontrar los metadatos.
Con una cabecera de 16 bytes, una solicitud de 96 bytes ocupa 112 bytes en total. El programa recibe un puntero situado 16 bytes después del comienzo del bloque. Al liberarlo se devuelve toda la extensión de 112 bytes, incluida la cabecera, para su gestión futura. La alineación puede añadir redondeo; los tamaños de estos ejemplos ya cumplen una alineación de 16 bytes.
Sigue una lista de bloques libres integrada
Supón que un montículo de 4096 bytes comienza en 32 768. Un nodo libre usa 16 bytes y registra los bytes utilizables después del nodo. Inicialmente registra 4080 bytes utilizables.
Tres solicitudes de 96 bytes consumen 112 bytes cada una:
| Solicitud | Dirección de la cabecera | Puntero devuelto |
|---|---|---|
| Primera | 32 768 | 32 784 |
| Segunda | 32 880 | 32 896 |
| Tercera | 32 992 | 33 008 |
El nodo libre restante comienza en 33 104. Su tamaño utilizable es de 3744 bytes. La contabilización es:
Liberar el puntero 32 896 permite encontrar la cabecera en 32 880. Ese bloque se convierte en un nodo libre con 96 bytes utilizables. No puede unirse al nodo final en 33 104 porque la tercera asignación está entre ambos. Cuando se liberan y fusionan las tres asignaciones, un solo nodo vuelve a describir 4080 bytes utilizables. Al absorber las antiguas cabeceras interiores, sus bytes quedan disponibles dentro de la extensión fusionada.
Mantén los registros dentro de la región gestionada
Los nodos integrados de la lista están en la propia memoria libre, por lo que gestionar la lista no requiere una asignación separada para cada entrada. El nodo contiene un tamaño y un enlace al siguiente bloque libre. Si ningún bloque sirve, el asignador puede solicitar más memoria con sbrk o mmap; si no consigue suficiente memoria, devuelve NULL.
Un desbordamiento puede sobrescribir una cabecera o un nodo vecino. Esto explica por qué el fallo visible puede producirse durante una llamada posterior a malloc o free, después de la escritura que dañó la lista.
Puntos clave
- Distingue el tamaño utilizable de la extensión total que incluye los metadatos.
- Una cabecera de 16 bytes hace que una solicitud de 96 bytes consuma 112 bytes.
- Encuentra la cabecera de una asignación restando su tamaño al puntero devuelto.
- La división conserva un resto utilizable; la fusión requiere extensiones libres adyacentes.
- Los nodos integrados almacenan los metadatos de la lista en los propios bloques libres.
- Un bloque vigente intermedio impide la fusión.
- Sobrescribir los registros puede causar fallos en llamadas posteriores al asignador.
5.3 Elección de un bloque libre
Una política de colocación elige entre los bloques suficientemente grandes para una solicitud. Las distintas elecciones dejan huecos diferentes para solicitudes futuras. El tiempo de búsqueda importa junto con la fragmentación, y ninguna política gana para todas las cargas de trabajo.
Compara las reglas de búsqueda
| Política | Elección | Principal contrapartida |
|---|---|---|
| Mejor ajuste | El bloque más pequeño que sirve | Una búsqueda completa en una lista sencilla puede dejar fragmentos diminutos. |
| Peor ajuste | El bloque más grande | Una búsqueda completa en una lista sencilla puede consumir un hueco grande valioso. |
| Primer ajuste | El primer bloque adecuado según el orden de la lista | Se detiene pronto, pero los sobrantes pequeños se acumulan cerca del comienzo. |
| Siguiente ajuste | El primer bloque adecuado desde una posición de búsqueda guardada | Distribuye las búsquedas por la lista y vuelve al comienzo cuando es necesario. |
Para el mejor y el peor ajuste, una lista sencilla sin ordenar necesita una búsqueda completa. Otras estructuras pueden encontrar tamaños adecuados más rápidamente. Primer ajuste significa primero en el orden elegido para la lista, lo que no tiene por qué significar la dirección más baja, salvo que la lista esté ordenada por dirección.
Sigue la primera solicitud
Considera bloques libres de 30, 12, 50 y 20 bytes en orden de dirección. Ignora las cabeceras y supón que la división puede conservar cada sobrante. Una solicitud de 18 bytes cambia la lista de la siguiente manera:
- El mejor ajuste usa 20 y deja 30, 12, 50, 2.
- El peor ajuste usa 50 y deja 30, 12, 32, 20.
- El primer ajuste usa 30 y deja 12, 12, 50, 20.
- El siguiente ajuste, si comienza en el cuarto bloque, usa 20 y deja 30, 12, 50, 2.
El siguiente ajuste necesita una posición inicial para determinar su elección. El nombre por sí solo no implica que sea la primera entrada de la lista. Un seguimiento debe conservar ese estado de búsqueda entre solicitudes.
Observa por qué la siguiente solicitud cambia la evaluación
Una solicitud posterior pide 45 bytes. El mejor ajuste y el primer ajuste conservaron el bloque de 50 bytes, por lo que ambos tienen éxito. El bloque restante más grande del peor ajuste es de 32 bytes, por lo que falla pese a tener 94 bytes libres en total:
Este fallo es fragmentación externa. La decisión anterior dividió el único hueco suficientemente grande. Por otra parte, el mejor ajuste dejó un fragmento de 2 bytes que puede ser demasiado pequeño para solicitudes futuras útiles. Un resto pequeño inmediato no demuestra que una política vaya a usar bien el espacio durante toda la secuencia de solicitudes.
Equilibra la política y la estructura de datos
Recorrer miles de entradas puede ser costoso incluso cuando cada colocación es buena. Los asignadores prácticos agrupan los bloques por tamaño o usan estructuras que facilitan la búsqueda, como árboles equilibrados. Una lista ordenada por dirección también facilita la fusión al hacer que los vecinos físicos sean más fáciles de encontrar.
El mecanismo de asignación (buscar, dividir, actualizar metadatos) puede seguir siendo el mismo mientras cambia la política. Para comparar políticas de forma justa, sigue las mismas solicitudes y liberaciones, mantén fijas las reglas de sobrecarga y ten en cuenta tanto los huecos resultantes como la cantidad de búsqueda.
Puntos clave
- El mejor ajuste elige el bloque suficiente más pequeño; el peor ajuste elige el más grande.
- El primer ajuste depende del orden de la lista; el siguiente ajuste también depende de la posición de búsqueda guardada.
- Una elección que atiende una solicitud puede impedir una solicitud posterior más grande.
- Ninguna política de colocación es la mejor para todas las cargas de trabajo.
- Las estructuras de datos afectan al coste de búsqueda independientemente de la regla de selección.
5.4 Reutilización de tamaños, objetos y bloques compañeros
La búsqueda general en una lista de bloques libres es flexible, pero puede ser costosa. Los asignadores especializados hacen que las solicitudes frecuentes sean predecibles al agrupar tamaños, conservar objetos reutilizables o restringir los tamaños de bloque a potencias de dos.
Reutiliza tamaños frecuentes y objetos inicializados
Las listas segregadas mantienen listas de bloques libres separadas para los tamaños frecuentes, con un asignador general para las demás solicitudes. Atender un tamaño habitual puede consistir en tomar un bloque directamente de su lista. Los bloques de igual tamaño no crean fragmentación externa entre sí, pero dividir la capacidad entre listas es una decisión de política: los bloques sobrantes de un tamaño pueden no servir para otro.
Un asignador por bloques de objetos mantiene una caché de objetos para un tipo de objeto del núcleo que se usa repetidamente, como un inodo, un cerrojo o un descriptor de proceso. Un bloque de objetos se divide en objetos de ese tipo. La caché obtiene más bloques cuando los necesita y puede devolver un bloque completamente libre a un asignador general. Jeff Bonwick diseñó este enfoque para Solaris.
La caché conserva los objetos liberados en un estado inicializado, evitando la configuración y destrucción repetidas. Esto ahorra tiempo además del de la búsqueda.
Divide una región de bloques compañeros
Un asignador binario por bloques compañeros comienza con una región de tamaño potencia de dos y redondea cada solicitud a un tamaño de bloque que sea potencia de dos. Divide repetidamente un bloque libre en mitades iguales hasta que una mitad tiene el tamaño justo. Las dos mitades de una división son bloques compañeros.
Para una solicitud de 5 KB en una región de 64 KB, redondea 5 KB a 8 KB. Divide 64 en dos bloques de 32 KB, después el bloque elegido de 32 en dos bloques de 16 KB y luego el bloque elegido de 16 en dos bloques de 8 KB. Devolver el primer bloque de 8 KB deja bloques compañeros libres en los desplazamientos 8 KB, 16 KB y 32 KB, con tamaños de 8 KB, 16 KB y 32 KB respectivamente.
La asignación desperdicia 3 KB dentro de su bloque de 8 KB. Esto es fragmentación interna, aceptada a cambio de una división y fusión regulares.
Encuentra el único compañero válido para la fusión
Usando desplazamientos medidos desde el comienzo de la región gestionada:
La operación O exclusiva invierte el bit correspondiente al tamaño del bloque. Para un bloque de 8 KB en el desplazamiento 0, su compañero está en el desplazamiento 8192. Para un bloque de 16 KB en el desplazamiento 16 384, su compañero está en 0.
Cuando se libera el primer bloque de 8 KB, se fusiona con su compañero libre de 8 KB. El bloque de 16 KB resultante puede fusionarse con su compañero libre y, después, el bloque de 32 KB resultante puede volver a fusionarse. La fusión se detiene si el compañero necesario del mismo tamaño está en uso. Estar adyacentes y libres no basta cuando dos bloques no son compañeros de la misma división.
Una solicitud de 20 KB recibe 32 KB y desperdicia 12 KB, o el 37,5 % del bloque. Linux combina la asignación por bloques compañeros de memoria física con cachés de objetos de tipo slab. Los asignadores multihilo también usan cachés locales o varias arenas para reducir la espera por un único cerrojo compartido de asignación; glibc, jemalloc y tcmalloc usan variantes de estas ideas.
Puntos clave
- Las listas segregadas aceleran las solicitudes de tamaños frecuentes.
- Las cachés de bloques de objetos reutilizan tipos de objetos frecuentes y pueden evitar la inicialización repetida.
- La asignación por bloques compañeros redondea a potencias de dos y divide en mitades iguales.
- El compañero se identifica mediante el desplazamiento relativo a la región XOR el tamaño del bloque.
- En cada nivel solo puede fusionarse un compañero libre del mismo tamaño.
- El redondeo a potencias de dos intercambia fragmentación interna por una gestión sencilla.
Ejemplos de Traducción de direcciones
1Sigue un puntero a través de una vista privada de la memoria
8 pasos
- 1IntroducciónUna máquina, varias vistas de la memoria
Varios procesos pueden permanecer en la memoria física mientras la CPU cambia entre ellos. Cada uno necesita una vista estable de sus propias instrucciones y datos, incluso cuando otros procesos comienzan, terminan o se mueven.
Un espacio de direcciones proporciona esa vista. El puntero que usa un proceso pertenece a ella; el sistema operativo y el hardware determinan el byte físico al que llega el acceso.
- 2ExplicaciónSitúa el contenido del programa
El código almacena instrucciones, los datos estáticos almacenan variables globales y locales estáticas, el montículo almacena bloques solicitados y la pila almacena el estado de las llamadas a funciones.
En la organización clásica, el montículo crece hacia arriba y la pila hacia abajo, en dirección al espacio que hay entre ambos. Con tamaños binarios, 1 KB significa 1024 bytes, también llamado 1 KiB. Un espacio de 16 KB tiene bytes de 0 a 16 383; su límite superior no es en sí mismo un byte del espacio.
- 3EjemploDa dos significados al mismo número
El proceso A y el proceso B usan ambos la dirección virtual 1000. La traducción de A puede enviarla a un byte físico mientras que la de B la envía a otro. El número del puntero por sí solo no identifica un almacenamiento compartido.
Del mismo modo, imprimir
&xmuestra una dirección virtual. Mover el almacenamiento físico subyacente no tiene por qué cambiar el valor del puntero que ve el programa. - 4DesafíoInterpreta dos punteros impresos
Dos procesos imprimen el mismo valor de puntero. ¿Deben estar leyendo el mismo byte físico? Explica qué determina el destino.
---reveal---
No. Cada puntero impreso se interpreta en el espacio de direcciones de su propio proceso. El mapeo activo determina el destino físico, por lo que números virtuales iguales pueden llegar a bytes distintos. Para llegar al mismo byte físico se necesitarían mapeos que compartieran realmente el almacenamiento.
- 5ExplicaciónTraduce con rapidez y haz cumplir los límites
La transparencia conserva la vista privada del programa. La eficiencia en tiempo mantiene bajo el coste de traducción en cada búsqueda, carga y almacenamiento. La eficiencia en espacio limita los metadatos y la capacidad desperdiciada. La protección detiene los accesos no autorizados.
El hardware gestiona la traducción ordinaria. El sistema operativo configura los mapeos, elige las ubicaciones y toma el control cuando un acceso genera una excepción.
- 6DesafíoSepara la elección de la operación
Un gestor de memoria pasa de elegir el primer hueco adecuado a elegir el hueco adecuado más pequeño. El hardware sigue comprobando los límites y sumando una base. ¿Cambió el mecanismo o la política?
---reveal---
Cambió la política de colocación: ahora hace una elección distinta entre los huecos. El mecanismo de traducción no cambió. El mismo hardware puede traducir y proteger una región independientemente del hueco adecuado que haya elegido el sistema operativo.
- 7DesafíoRelaciona el movimiento con la protección
Un sistema operativo mueve un proceso pausado a una nueva región física, pero conserva los valores de sus punteros. ¿Por qué requiere esto tanto traducción como control sobre quién puede cambiar el mapeo?
---reveal---
La traducción redirige los punteros virtuales sin cambiar a los bytes copiados. Solo el código privilegiado del sistema operativo puede instalar el nuevo mapeo; de lo contrario, un proceso podría redirigirse hacia otro proceso o hacia el núcleo. Los punteros estables proporcionan transparencia, mientras que los mapeos controlados conservan el aislamiento.
- 8RepasoInterpreta el puntero en su proceso
Un espacio de direcciones organiza el código y los datos de un proceso independientemente de su ubicación física. Un puntero virtual adquiere significado mediante el mapeo del proceso en ejecución.
Evalúa un diseño por la vista que conserva, sus costes de tiempo y espacio y los límites de acceso que hace cumplir. Las políticas eligen las ubicaciones; los mecanismos realizan la traducción y las comprobaciones.
2Sigue una solicitud de montículo por la biblioteca y el sistema operativo
12 pasos
Guarda esta unidad para seguir cada Lección Interactiva paso a paso.
- 1IntroducciónTen presentes a los dos propietarios
- 2EjemploSepara un puntero de su asignación
- 3ExplicaciónSolicita suficientes bytes
- 4DesafíoPredice qué permanece tras un retorno
- 5ExplicaciónLibera solo un bloque vigente
- 6Idea claveUna región permitida puede contener un acceso no válido a un objeto
- 7ExplicaciónAmplía una región y después divídela
- 8DesafíoLocaliza los bytes recién añadidos
- 9ConexiónLibera un bloque o elimina un mapeo
- 10DesafíoExplica una ocupación estable de memoria
- 11DesafíoSigue el crecimiento mediante segmentación
- 12RepasoSigue por separado el tiempo de vida y la propiedad
3Ejecuta y mueve un proceso con base y límite
13 pasos
Guarda esta unidad para seguir cada Lección Interactiva paso a paso.
- 1IntroducciónDescribe una ranura física
- 2ExplicaciónAplica la convención de tamaño
- 3EjemploTraduce la búsqueda y la carga
- 4DesafíoComprueba el último byte
- 5ConsejoReconoce la alternativa para el registro límite
- 6ExplicaciónProtege los registros de traducción
- 7EjemploCambia la vista de memoria junto con el estado de la CPU
- 8DesafíoDetecta una restauración omitida
- 9ConexiónMueve un proceso sin reescribir punteros
- 10EjemploMide la extensión sin usar
- 11DesafíoElige la unidad de reubicación
- 12DesafíoMantén el límite después de mover un proceso
- 13RepasoDistingue las coordenadas y los costes
4Traduce código, montículo y una pila que crece hacia abajo
17 pasos
Guarda esta unidad para seguir cada Lección Interactiva paso a paso.
- 1IntroducciónDivide el proceso en regiones lógicas
- 2ExplicaciónEstablece la organización del ejemplo
- 3EjemploEncuentra el desplazamiento dentro del montículo
- 4DesafíoComprueba un byte fuera del montículo
- 5ExplicaciónUsa bits selectores para elegir registros
- 6EjemploExtrae ambos campos
- 7DesafíoSepara la capacidad del uso actual
- 8ConexiónDeja que el acceso elija un segmento
- 9ExplicaciónMide hacia abajo desde un límite superior
- 10EjemploCalcula un desplazamiento de pila con signo
- 11DesafíoIncluye el byte de dirección más baja de la pila
- 12Idea claveComprueba el permiso después de encontrar una ubicación válida
- 13ExplicaciónRestaura más que una base
- 14DesafíoCuenta los huecos por separado
- 15ConexiónComprende los límites de la compactación
- 16DesafíoMueve un segmento compartido de forma segura
- 17RepasoEncuentra la región antes que el byte físico
5Sigue los bloques libres y elige políticas de asignación
18 pasos
Guarda esta unidad para seguir cada Lección Interactiva paso a paso.
- 1IntroducciónPregunta si cabe en un solo bloque
- 2EjemploLocaliza la capacidad sin usar
- 3DesafíoComprueba qué puede lograr la fusión
- 4ConexiónExplica por qué los punteros a bloques vigentes impiden compactar el montículo
- 5ExplicaciónTen en cuenta la cabecera
- 6EjemploColoca tres bloques
- 7EjemploComprueba la extensión restante
- 8DesafíoRecupera una cabecera y una extensión
- 9ExplicaciónDeja que la política elija el bloque
- 10EjemploCompara la primera elección
- 11DesafíoMira la siguiente solicitud
- 12ConexiónHaz predecibles las solicitudes frecuentes
- 13EjemploRedondea y divide una región de bloques compañeros
- 14ExplicaciónEncuentra el bloque compañero correspondiente
- 15DesafíoSigue los niveles de fusión
- 16Idea clavePaga la simplicidad dentro del bloque
- 17DesafíoSepara la colocación de la fusión
- 18RepasoSigue tanto la organización como la contabilización
Ejercicios de Traducción de direcciones
Set 1: Espacios de direcciones, comprobaciones y primeras asignaciones10 Preguntas de Práctica
Pregunta 1 de 10
Mostrar respuestaOcultar respuesta
Pregunta 2 de 10
Mostrar respuestaOcultar respuesta
Pregunta 3 de 10
Mostrar respuestaOcultar respuesta
Pregunta 4 de 10
sizeof(p) cuando p contiene la dirección de la asignación?Mostrar respuestaOcultar respuesta
sizeof(p) es el objeto puntero, cuyo tamaño indicado es de 8 bytes. La asignación contiene 48 bytes, pero sizeof no sigue un puntero para medir un bloque del montículo. Usar aquí el tamaño de la asignación confunde el puntero con aquello a lo que apunta.Pregunta 5 de 10
Mostrar respuestaOcultar respuesta
Pregunta 6 de 10
Mostrar respuestaOcultar respuesta
Pregunta 7 de 10
Mostrar respuestaOcultar respuesta
Pregunta 8 de 10
Mostrar respuestaOcultar respuesta
Pregunta 9 de 10
Mostrar respuestaOcultar respuesta
Pregunta 10 de 10
Mostrar respuestaOcultar respuesta
Set 2: Cambios de proceso y decisiones de colocación10 Preguntas de Práctica
Guarda esta unidad para ver todas las respuestas y practicar cada set.
Pregunta 1 de 10
Mostrar respuestaOcultar respuesta
Guarda esta unidad para ver esta respuesta.
Pregunta 2 de 10
sbrk(4096) amplía el montículo. ¿Cuáles son el valor devuelto y el nuevo límite?Mostrar respuestaOcultar respuesta
Guarda esta unidad para ver esta respuesta.
Pregunta 3 de 10
Mostrar respuestaOcultar respuesta
Guarda esta unidad para ver esta respuesta.
Pregunta 4 de 10
Mostrar respuestaOcultar respuesta
Guarda esta unidad para ver esta respuesta.
Pregunta 5 de 10
Mostrar respuestaOcultar respuesta
Guarda esta unidad para ver esta respuesta.
Pregunta 6 de 10
Mostrar respuestaOcultar respuesta
Guarda esta unidad para ver esta respuesta.
Pregunta 7 de 10
Mostrar respuestaOcultar respuesta
Guarda esta unidad para ver esta respuesta.
Pregunta 8 de 10
Mostrar respuestaOcultar respuesta
Guarda esta unidad para ver esta respuesta.
Pregunta 9 de 10
Mostrar respuestaOcultar respuesta
Guarda esta unidad para ver esta respuesta.
Pregunta 10 de 10
Mostrar respuestaOcultar respuesta
Guarda esta unidad para ver esta respuesta.
Set 3: Seguimiento de límites y del estado del asignador10 Preguntas de Práctica
Guarda esta unidad para ver todas las respuestas y practicar cada set.
Pregunta 1 de 10
Mostrar respuestaOcultar respuesta
Guarda esta unidad para ver esta respuesta.
Pregunta 2 de 10
Mostrar respuestaOcultar respuesta
Guarda esta unidad para ver esta respuesta.
Pregunta 3 de 10
Mostrar respuestaOcultar respuesta
Guarda esta unidad para ver esta respuesta.
Pregunta 4 de 10
Mostrar respuestaOcultar respuesta
Guarda esta unidad para ver esta respuesta.
Pregunta 5 de 10
Mostrar respuestaOcultar respuesta
Guarda esta unidad para ver esta respuesta.
Pregunta 6 de 10
Mostrar respuestaOcultar respuesta
Guarda esta unidad para ver esta respuesta.
Pregunta 7 de 10
Mostrar respuestaOcultar respuesta
Guarda esta unidad para ver esta respuesta.
Pregunta 8 de 10
Mostrar respuestaOcultar respuesta
Guarda esta unidad para ver esta respuesta.
Pregunta 9 de 10
Mostrar respuestaOcultar respuesta
Guarda esta unidad para ver esta respuesta.
Pregunta 10 de 10
Mostrar respuestaOcultar respuesta
Guarda esta unidad para ver esta respuesta.
Set 4: Explicación de fallos y conservación de mapeos10 Preguntas de Práctica
Guarda esta unidad para ver todas las respuestas y practicar cada set.
Pregunta 1 de 10
Mostrar respuestaOcultar respuesta
Guarda esta unidad para ver esta respuesta.
Pregunta 2 de 10
Mostrar respuestaOcultar respuesta
Guarda esta unidad para ver esta respuesta.
Pregunta 3 de 10
Mostrar respuestaOcultar respuesta
Guarda esta unidad para ver esta respuesta.
Pregunta 4 de 10
Mostrar respuestaOcultar respuesta
Guarda esta unidad para ver esta respuesta.
Pregunta 5 de 10
Mostrar respuestaOcultar respuesta
Guarda esta unidad para ver esta respuesta.
Pregunta 6 de 10
Mostrar respuestaOcultar respuesta
Guarda esta unidad para ver esta respuesta.
Pregunta 7 de 10
Mostrar respuestaOcultar respuesta
Guarda esta unidad para ver esta respuesta.
Pregunta 8 de 10
Mostrar respuestaOcultar respuesta
Guarda esta unidad para ver esta respuesta.
Pregunta 9 de 10
Mostrar respuestaOcultar respuesta
Guarda esta unidad para ver esta respuesta.
Pregunta 10 de 10
Mostrar respuestaOcultar respuesta
Guarda esta unidad para ver esta respuesta.
Set 5: Razonamiento combinado sobre traducción y asignación10 Preguntas de Práctica
Guarda esta unidad para ver todas las respuestas y practicar cada set.
Pregunta 1 de 10
Mostrar respuestaOcultar respuesta
Guarda esta unidad para ver esta respuesta.
Pregunta 2 de 10
sbrk(1500). ¿Qué devuelve sbrk y dónde se encuentra ahora el primer byte existente del montículo?Mostrar respuestaOcultar respuesta
Guarda esta unidad para ver esta respuesta.
Pregunta 3 de 10
Mostrar respuestaOcultar respuesta
Guarda esta unidad para ver esta respuesta.
Pregunta 4 de 10
Mostrar respuestaOcultar respuesta
Guarda esta unidad para ver esta respuesta.
Pregunta 5 de 10
Mostrar respuestaOcultar respuesta
Guarda esta unidad para ver esta respuesta.
Pregunta 6 de 10
Mostrar respuestaOcultar respuesta
Guarda esta unidad para ver esta respuesta.
Pregunta 7 de 10
Mostrar respuestaOcultar respuesta
Guarda esta unidad para ver esta respuesta.
Pregunta 8 de 10
Mostrar respuestaOcultar respuesta
Guarda esta unidad para ver esta respuesta.
Pregunta 9 de 10
Mostrar respuestaOcultar respuesta
Guarda esta unidad para ver esta respuesta.
Pregunta 10 de 10
Mostrar respuestaOcultar respuesta
Guarda esta unidad para ver esta respuesta.
¿Te atascas con una pregunta tuya? Ayuda con Tareas
Términos Clave
A
Aislamiento
Almacenamiento estático
Arena de asignación
Asignador por bloques compañeros
Asignador por bloques de objetos
B
Bits de protección
Bloque asignado vigente
Bloque compañero
Bloque de control de proceso
brk
brk establece el límite final del montículo tradicional en una dirección especificada, lo que permite al asignador cambiar el tamaño de esa región.C
Cabecera de asignación
free.calloc
calloc es una función de asignación de la biblioteca C que proporciona almacenamiento lleno de bytes de valor cero, a diferencia del almacenamiento sin poner a cero que devuelve malloc.calloc comienza con bytes de valor cero antes de que el programa escriba datos.Cambio de contexto
Campo de desplazamiento
Carga útil
Compactación
Compartición de código
Contención de cerrojos
D
Desbordamiento de búfer
Desplazamiento dentro del segmento
Desplazamiento negativo
Dirección de crecimiento
Dirección física
Dirección virtual
División de bloques
Doble liberación de memoria
free dos veces mediante punteros copiados a un mismo bloque puede corromper el estado de la biblioteca de asignación.E
Espacio de direcciones
Espacio de direcciones disperso
F
Fallo de segmentación
Fragmentación externa
Fragmentación interna
free
free es una función de la biblioteca C que devuelve un bloque asignado vigente al asignador; pasarle NULL está permitido y no tiene efecto.Fuga de memoria
Fusión de bloques libres adyacentes
G
Gestión del espacio libre
I
Instrucción privilegiada
L
Lectura de memoria sin inicializar
malloc.Límite del montículo
Lista de bloques libres
Listas segregadas
M
malloc
malloc es una función de la biblioteca C que solicita un bloque de un tamaño en bytes y devuelve su dirección, o NULL si falla, sin poner a cero su contenido.malloc(6 * sizeof(int)) para tener en cuenta el tamaño del elemento.Manejador de excepciones
Mapeo anónimo
mmap.Máscara de bits
va & 0x0FFF conserva doce bits inferiores mientras pone a cero los dos bits de segmento de una dirección de catorce bits.Mecanismo
Mejor ajuste
Montículo
munmap
munmap elimina una región mapeada del espacio de direcciones de un proceso, a diferencia de devolver un bloque pequeño a una reserva de la biblioteca para reutilizarlo.N
Nodo de lista libre integrado en el bloque
P
Peor ajuste
Permiso de lectura y ejecución
Pila
Política
Primer ajuste
Puntero colgante
R
realloc
realloc es una función de la biblioteca C que cambia el tamaño de un bloque asignado y puede mover su contenido a un bloque en una dirección distinta.Redondeo del tamaño de asignación
Región contigua
Registro base
Registro límite
Reubicación dinámica
Reubicación estática
S
sbrk
sbrk cambia el límite del montículo según un incremento de bytes solicitado y devuelve el límite anterior si tiene éxito; un incremento de cero indica el límite actual.sbrk(1024) con el límite en 20 000 devuelve 20 000 y deja el nuevo límite en 21 024.Segmentación
Segmentación de grano fino
Segmentación de grano grueso
Segmento
Selección implícita de segmento
Selector de segmento
01 pueden seleccionar el montículo mientras los doce bits inferiores localizan su byte.Siguiente ajuste
T
Tabla de segmentos
Transparencia
U
Unidad de gestión de memoria
Sobre esta unidad
Crea tus propios Materiales de Estudio
Convierte tus notas, diapositivas y documentos en Guías de Estudio, Preguntas de Práctica, Flashcards y 6 herramientas más.