En informática la segmentación de memoria es una técnica de gestión de memoria que pretende acercarse más al punto de vista del usuario. Los programas se desarrollan, generalmente, en torno a un núcleo central (principal) desde el que se bifurca a otras partes (rutinas) o se accede a zonas de datos (tablas, pilas, etc).
Desde este punto de vista, un programa es un conjunto de componentes lógicos de tamaño variable o un conjunto de segmentos, es decir, el espacio lógico de direcciones se considera como un conjunto de segmentos, cada uno definido por un identificador, y consistente de un punto de inicio y el tamaño asignado.[1]
La segmentación de un programa la realiza el compilador y en ella cada dirección lógica se expresará mediante dos valores: Número de segmento (s) y desplazamiento dentro del segmento (d).
Una de las implementaciones más obvias y directas de un espacio de memoria segmentado es asignar un segmento distinto a cada una de las secciones del espacio en memoria de un proceso.
La segmentación también ayuda a incrementar la modularidad de un programa: Es muy común que las bibliotecas enlazadas dinámicamente estén representadas en segmentos independientes.
Hardware de segmentación
Puesto que la memoria física se direcciona literalmente, será necesario transformar cada dirección lógica en una dirección real . Esta conversión la realiza un dispositivo especial de hardware, consultando la tabla de segmentos correspondiente.
Rendimiento
Esta técnica permite reducir la fragmentación interna de la memoria provocada por la paginación, ya que asigna a cada programa la cantidad de memoria que requiere.
La carga de un programa en memoria exige la búsqueda de los huecos adecuados a sus segmentos, y puesto que éstos son de tamaño variable, se ajustarán los más posible a las necesidades, produciéndose huecos pequeños. En este caso se produce fragmentación externa. La eficiencia de la segmentación requiere, de igual forma que la paginación, el uso de memorias caché para lograr unos tiempos de acceso adecuados. De igual forma que en la paginación, se pueden compartir segmentos entre varios procesos.
Permisos
Una de las principales ventajas del uso de segmentación es que nos permite pedir a la unidad de gestión de memoria que cada uno de los segmentos tenga un distinto juego de permisos[2] para el proceso en cuestíón: El sistema operativo puede indicar, por ejemplo, que el segmento de texto (el código del programa) sea de lectura y ejecución, mientras que la sección de datos es de lectura y escritura. De este modo podemos evitar que un error en la programación resulte en que datos proporcionados por el usuario o por el entorno modifiquen el código que está siendo ejecutado.
Sin embargo, incluso bajo este esquema, dado que la pila de llamadas (stack) debe mantenerse como escribible, es común encontrar ataques que permiten modificar la dirección de retorno de una subrutina.
Incluso, dado que el acceso de ejecución está limitado a solo los segmentos cargados del disco por el sistema operativo, el atacante no podrá introducir código ejecutable tan fácilmente — Tendría que cargarlo como un segmento adicional con los permisos correspondientes.
Intercambio parcial
Un uso muy común de la segmentación, particularmnete en los sistemas de los 1980s, era el de permitir que solo ciertas regiones de un programa sean intercambiadas al disco: Si un programa está compuesto por porciones de código que nunca se ejecutarán aproximadamente al mismo tiempo en sucesión, puede separar su texto (e incluso los datos correspondientes) en diferentes segmentos.
A lo largo de la ejecución del programa, algunos de sus segmentos pueden no emplearse por largos periodos de tiempo. Estas páginas pueden ser enviadas al espacio de intercambio (swap) ya sea a solicitud del proceso o por iniciativa del sistema operativo.
Rendimiento
Intercambiar un proceso completo a disco resulta demasiado caro. Cuando hablamos de un espacio de memoria segmentado, y muy particularmente cuando hablamos de bibliotecas de carga dinámica, la sobrecarga es mucho menor: Si el segmento de texto es de solo lectura, una vez que este fue copiado una vez al disco, ya no hace falta volver a hacerlo: Tenemos la certeza de que no será modificado por el proceso en ejecución, por lo que basta marcarlo como no presente en las tablas de segmentos en memoria para que cualquier acceso ocasione que el sistema operativo lo traiga de disco.
Por otro lado, si la biblioteca en cuestión reside en disco (antes de ser cargada) como una imagen directa de su representación en memoria, al sistema operativo le bastará identificar el archivo en cuestión al cargar el proceso; no hace falta siquiera cargarlo en la memoria principal y guardarlo al área de intercambio, puede quedar referido directamente al espacio en disco en que reside el archivo.
Claro está, el acceso a disco sigue siendo una fuerte penalización cada vez que un segmento tiene que ser cargado del disco (sea del sistema de archivos o del espacio de intercambio), pero este mecanismo reduce dicha penalización, haciendo más atractiva la flexibilidad del intercambio por segmentos.
Referencias
- ↑ Operating Systems Concepts Essentials; Abraham Silberschatz, Peter Baen Galvin, Greg Gagne; John Wiley & Sons, 2011
- ↑ An Operating Systems Vade Mecum, Raphael Finkel, University of Kentucky, 1988