Memoria, y más memoria
La memoria es el elemento más utilizado de un ordenador, y desde nuestros programas estamos continuamente accediendo a ella, ya sea para leer las instrucciones que debemos ir ejecutando, como para leer/escribir los datos con los que operamos. Aunque desde el punto de vista del hardware, la memoria siempre es igual (chips con megas y más megas, y cada byte numerado con una dirección única), el modo de gestionarla que tiene el sistema operativo y la manera de permitirnos acceder a ella ha ido evolucionando durante los últimos tiempos.
Si volvemos al pasado unos cuantos años y hacemos un programa para MS-DOS (que no es lo mismo que un programa de consola para Windows), el sistema operativo nos da acceso a toda memoria, se fía de nosotros (je je, pobre, no sabe el error que está cometiendo). Es decir, desde MS-DOS podemos acceder con un puntero al byte 0, al 5784 o al que queramos, y de este modo nos estaremos metiendo donde nadie nos ha llamado.
Desde nuestros programas esto es muy sencillo, incluso en Pascal hay dos maneras de realizarlo:
1.- Forzando al linker que sitúe una variable en una posición de memoria determinada, a través de la cláusula absolute:
var
a: integer absolute $FFFF;
2.- Direccionando un puntero a una dirección de memoria fija (al estilo C):
type
Pinteger = ^integer;
var
p: PInteger;
begin
p := PInteger($FFFF);
[...]
end;
Ambas opciones son válidas, pero… sólo si el sistema operativo realmente nos da acceso a esa zona de memoria.
Esto tiene su parte buena: control absoluto. Una utilidad típica a esto solía ser direccionar un puntero hacia la zona de memoria de la pantalla, y escribir directamente en ella, como si fuera una matriz de caracteres. Con eso se conseguía una rapidez similar a la del ensamblador a la hora de dibujar en la pantalla. Otra ventaja era que dos programas residentes en memoria podían comunicarse muy fácilmente entre si, ya que el uno podía ver la memoria del otro.
Por su contra, el sistema era tremendamente inestable, ya que lo más normal es que los punteros se nos fueran de madre y acabásemos sobrescribiendo los datos o el código de otros programas, o lo que podía ser peor: machacar el sistema operativo ¡¡o incluso la BIOS!!
Allá cuando nació Windows 3.x, las cosas cambiaron ligeramente, ya que la gente de Microsoft comenzó a verificar que no sobrescribiesemos algunas zonas de memoria donde residía el sistema operativo. Cuando intentábamos escribir en alguna zona protegida, Windows lanzaba un Access Violation para defenderse de los intrusos. De este modo se conseguía un sistema más estable, aunque en aquella época no era posible mucho más, ya que todavía podíamos tocarle las tripas a zonas de memoria de otros procesos, y eso hacía que si fallaba nuestro programa (por escribir en la memoria del vecino) hiciésemos que otros procesos se fuesen al traste, todo en cascada. Internamente teníamos toda la memoria para nosotros, pero no podríamos leer ni escribir en zonas protegidas por Windows. Este sistema de memoria es lo que llamaron el famoso “Modo protegido” de Windows.
A partir de la introducción de Windows 95 comenzó la era de los 32 bits, o lo que es lo mismo para Window-hablantes: la era de la arquitectura Win32. Esto puede poner los pelos de punta a más de uno, porque realmente hay cosas con las que hemos ido a peor (ahora nos encontramos las siglas M$ hasta en la sopa), pero también hay que decir que con Win32 el sistema completo se vuelve más estable, a la vez que más escalable. Al César lo que es del César.
Ahora vamos a ver porqué me atrevo a decir esto.
Modelo de memoria plano
Cada vez que hacemos doble clic sobre un ejecutable (o cualquier otra manera de iniciar un programa), Windows llamará a la función CreateProcess para iniciar un nuevo proceso. Una de las cosas que hace esta función (entre otras muchas) es crear un espacio privado de direcciones virtuales de 4 GB… ¿Mandeeeeeeeee? A muchos lo único que le sonará familiar son los 4 GB, porque el resto parece chino. No es tan complicado, esto significa que Windows considera que tenemos una memoria de 4 GB (casi ná) y encima toda para nosotros. Así que disponemos de un rango de direcciones desde $00000000 hasta $FFFFFFFF, desde 0 hasta 11111111111111111111111111111111 (que nadie los cuente, que son 32 bits) o en cristiano: desde el byte 0 al byte número 4.294.967.295.
En teoría podríamos recorrernos ese rango a través de un puntero y todo funcionaría. Y digo en teoría porque las cosas no son tan sencillas, pero luego veremos por qué. A este modo de gestionar la memoria se le denomina “Modelo de memoria plano”.
Que tengamos un espacio de direcciones de 4 GB no significa que tengamos 4 GB de memoria RAM instalada (a ver quien es el afortunado), sino que la suma entre la memoria RAM física, y la memoria virtual puede llegar a 4 GB. ¿Y qué es la memoria virtual?
Memoria Virtual
Es un tipo de memoria que utiliza el sistema, pero en vez de almacenarse en los chips de la memoria RAM, se almacena en un archivo que está en nuestro disco duro.