PDF de programación - Capítulo 16. Memoria virtual

Capítulo 16. Memoria virtualgráfica de visualizaciones

Publicado el 17 de Julio del 2017
396 visualizaciones desde el 17 de Julio del 2017
94,5 KB
5 paginas
Creado hace 9a (31/07/2014)
Capítulo 16. Memoria virtual

16.1. Objetivos

Entender el espacio de direcciones virtual de los procesos.

16.2. Documentación de las transparencias

Las transparencias relevantes para realizar esta práctica son:
- Páginas 31-35 de las transparencias de Bibliotecas de C y llamadas al sistema

16.3. Especificación

16.3.1. Examen del espacio de direcciones virtuales de los
procesos
Examine el espacio de direcciones virtuales de distintos procesos mirando ficheros maps del sistema
de ficheros del núcleo proc (montado en el directorio /proc). Este sistema de ficheros proporciona
información mantenida por el núcleo y, además, puede servir para configurarlo. En particular, hay
directorios cuyos nombres son los números de procesos en ejecución y, dentro de ellos puede
encontrarse información sobre dichos procesos. Por ejemplo, puede hacer cat /proc/1534/maps
para ver el espacio de direcciones del proceso 1534 1. O cat /proc/self/maps, para el del proceso
en curso, que tendrá el programa cat (el enlace simbólico /proc/self apunta siempre al proceso en
ejecución que lo mira).
La información que puede ver está estrucurada en forma de tabla de seis columnas:

Direcciones Protecciones

Rango de
direcciones
virtuales.

y modo de
compartición
r si se puede
leer, w si se
puede escribir, x
si se puede
ejecutar, s si se
comparte con
otros procesos,
p si es privado;
es decir, se
comparte, pero
se duplican las
páginas donde
se escribe.

DesplazamientoDispositivo

Inodo

Desplazamiento
del segmento en
el fichero, si es
que el segmento
ha venido de
fichero.

Dispositivo
físico de
respaldo del
segmento
(número mayor
y menor), si es
que el segmento
ha venido de
fichero.

Número de
inodo de
respaldo del
segmento, si es
que el segmento
ha venido de
fichero.

Nombre de
fichero

Nombre del
fichero respaldo
del segmento, si
es que el
segmento ha
venido de
fichero. Aquí
veremos el
código y los
datos
inicializados del
programa, el
cargador
dinámico, las
bibliotecas
dinámicas
usadas,
catálogos de
mensajes, etc.

Por ejemplo, este puede ser el contenido de /proc/self/maps si lo leemos con cat:

1

00350000-00370000 r-xp 00000000 2b:00 198618
00370000-00371000 r--p 0001f000 2b:00 198618
00371000-00372000 rw-p 00020000 2b:00 198618
0083e000-009dd000 r-xp 00000000 2b:00 198667
009dd000-009df000 r--p 0019f000 2b:00 198667
009df000-009e0000 rw-p 001a1000 2b:00 198667
009e0000-009e3000 rw-p 00000000 00:00 0
00db3000-00db4000 r-xp 00000000 00:00 0
08048000-08053000 r-xp 00000000 2b:00 199845
08053000-08054000 r--p 0000a000 2b:00 199845
08054000-08055000 rw-p 0000b000 2b:00 199845
0999d000-099be000 rw-p 00000000 00:00 0
b757c000-b777c000 r--p 00000000 2b:00 72820
b777c000-b777d000 rw-p 00000000 00:00 0
b7790000-b7792000 rw-p 00000000 00:00 0
bfc89000-bfcaa000 rw-p 00000000 00:00 0

Capítulo 16. Memoria virtual

/rofs/lib/i386-linux-gnu/ld-2.15.so
/rofs/lib/i386-linux-gnu/ld-2.15.so
/rofs/lib/i386-linux-gnu/ld-2.15.so
/rofs/lib/i386-linux-gnu/libc-2.15.so
/rofs/lib/i386-linux-gnu/libc-2.15.so
/rofs/lib/i386-linux-gnu/libc-2.15.so

[vdso]
/rofs/bin/cat
/rofs/bin/cat
/rofs/bin/cat
[heap]
/rofs/usr/lib/locale/locale-archive

[stack]

Observe que la memoria virtual de los procesos se divide en regiones. En este caso la novena región
contiene el código del programa, con permisos de lectura y ejecución, contenido en el fichero
/bin/cat (inodo 199845 del dispositivo 2b:00). La undécima región contiene los datos estáticos,
con permisos de lectura y escritura, contenidos a partir de la posición 0xb000 del mismo fichero. La
duodécima región no está respaldada por disco, y está destinada a memoria dinámica del proceso.
Las regiones cuarta a sexta corresponden a la biblioteca estándar de C, y la primera a tercera al
cargador dinámico, que hace posible que el programa enlace correctamente con la biblioteca. La
dieciseis corresponde a la pila y está muy alejada del resto, para que pueda crecer hacia abajo. Mire
el manual del sistema de ficheros proc para más información (man 5 proc).

16.3.2. Determinación de direcciones virtuales
El siguiente programa direcciones.c, imprime en hexadecimal la dirección virtual de diversas partes
de sí mismo. Ejecútelo y explique, razonadamente, en qué región está cada dirección impresa.

#include <stdlib.h>
#include <stdio.h>

char e1[0x100], e2[0x100];

char *m = "Hola amigo";

void escribe(char *texto, void *dir) {
printf("DirecciÃ3n de %-4s = %10x (%10u)\n",

texto, (unsigned int)dir, (unsigned int)dir);

}

int main(void) {
char *p1 = malloc(0x1000);
char *p2 = malloc(0x1000);
escribe("main", main);
escribe("e1", &e1);
escribe("e2", &e2);
escribe("m", &m);
escribe("*m", m);
escribe("p1", &p1);
escribe("p2", &p2);
escribe("*p1", p1);
escribe("*p2", p2);
sleep(1000);

}

2

Capítulo 16. Memoria virtual

Para entender completamente los resultados puede añadir al final del programa una espera larga (por
ejemplo, sleep(200);) y lanzarlo en background, procediendo a examinar el fichero
/proc/número_de_proceso/maps).

16.3.3. Determinación de la accesibilidad de direcciones
virtuales propias
El siguiente programa accesible.c intenta determinar la accesibilidad en lectura y escritura de la
dirección virtual que se le pasa como parámetro (en decimal, a menos que empiece por 0, que será
octal, o por 0x, que será hexadecimal). Los accesos a direcciones no disponibles ocasionan una
excepción (SIGSEGV o violación de segmento), que es tratada por las rutinas nolee y noescribe,
gracias a la operación signal.

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>

char dato; char *dir;

void nolee(int s) {

no legible\n");

printf("
sleep(1000);
exit(0);

}

void noescribe(int s) {

no escribible\n");

printf("
sleep(1000);
exit(0);

}

int main(int argc, char *argv[]) {

if (argc != 2) {

fprintf(stderr, "%s: se necesita una direccion\n", argv[0]);
exit(1);

}
dir = (char *)strtoul(argv[1], NULL, 0);
printf(

"Probando la direccion virtual 0x%x (%u)\n",
(unsigned int)dir, (unsigned int)dir);

legible\n");

signal(SIGSEGV, nolee);
dato = *dir;
printf("
signal(SIGSEGV, noescribe);
*dir = dato;
printf("
sleep(1000);
exit(0);

escribible\n");

}

Determine la accesibilidad de direcciones virtuales significativas para el programa, como la 0, y
otras que puedan estar en zonas de datos y de código. Será necesario utilizar el mismo truco de antes
(un sleep antes de cada exit y mirar el mapa de memoria mientras no termina). Observe que
algunas implementaciones de Linux, como la del laboratorio, ponen la pila y el montículo en una
dirección aleatoria, por motivos de seguridad.

3

Capítulo 16. Memoria virtual

16.3.4. Exploración del espacio de direcciones virtuales
El siguiente programa explora.c intenta acceder en lectura a la primera posición de todas las páginas
su espacio de memoria virtual, informando de los rangos de direcciones legibles. Los accesos a
direcciones no legibles ocasionan una excepción (SIGSEGV o violación de segmento), que es tratada
por la rutina viola, gracias a la operación signal. Después de esta excepción, no puede
reintentarse la instrucción. Por ello se guarda el estado al comienzo del bucle de barrido con
sigsetjmp y se salta ahí con siglongjmp. Ejecútelo e interprete los resultados2.

#include <unistd.h>
#include <stdio.h>
#include <signal.h>
#include <setjmp.h>
#include <stdlib.h>

typedef enum {si, no, no_sabe, me_da_igual} legibilidad;

char *dir, *dir0;
legibilidad acc0;
int tpagina;
sigjmp_buf estado;

void imprime_rango(char *d1, char* d2, legibilidad acc) {

printf("%8x-%8x (%10u-%10u) ", (unsigned int)d1,

(unsigned int)d2, (unsigned int)d1, (unsigned int)d2);

if (acc == si) printf("legible\n");
else printf("ilegible\n");

}

void informa(legibilidad acc) { /* Sólo imprime rangos */

if (acc0 == no_sabe) acc0 = acc;
else

if (acc != acc0) {

imprime_rango(dir0, dir-1, acc0);
dir0 = dir; acc0 = acc;

}

dir = dir + tpagina;
if (dir == NULL) {

imprime_rango(dir0, dir-1, acc);
exit(0);

}

}

void viola(int s) { /* Procesa violaciones de memoria */

informa(no);
siglongjmp(estado, 1);

}

int main(void) {

char dato;
tpagina = getpagesize();
acc0 = no_sabe;
dir = NULL; dir0 = dir;
signal(SIGSEGV, viola);
sigsetjmp(estado, 1); /* Salva estado, incluido tratamiento de señales */
for (;;) {

dato = *dir;
informa(si);

/* Si es ilegible, no se ejecuta */

}

}

4

Capítulo 16. Memoria virtual

Compare los resultados con el mapa del propio proceso en ejecución, que puede obtener como antes,
insertando una instrucción sleep al final y lanzándolo en background.

16.4. Ficheros ofrecidos

En el directorio memoria:

• Programa direcciones.c.
• Programa accesible.c.
• Programa explora.c.

16.5. Resultados pedidos

• Región correspondiente a cada direción impresa por direcciones.c.
• Accesibilidad de al menos las direcciones virtuales 0, una de código y otra de datos del programa

accesible.c.

• Mapa de accesibilidad de regiones de explora.c, comentado.

Notas

1. En algunas versiones de Linux, como la del laboratorio, el fichero maps sólo es legible por el

propietario del proceso.

2. Los programas que usen estas funciones deben compilarse sin optimizar, ya que el compilador

desconoce su significado.

5
  • Links de descarga
http://lwp-l.com/pdf5440

Comentarios de: Capítulo 16. Memoria virtual (0)


No hay comentarios
 

Comentar...

Nombre
Correo (no se visualiza en la web)
Valoración
Comentarios...
CerrarCerrar
CerrarCerrar
Cerrar

Tienes que ser un usuario registrado para poder insertar imágenes, archivos y/o videos.

Puedes registrarte o validarte desde aquí.

Codigo
Negrita
Subrayado
Tachado
Cursiva
Insertar enlace
Imagen externa
Emoticon
Tabular
Centrar
Titulo
Linea
Disminuir
Aumentar
Vista preliminar
sonreir
dientes
lengua
guiño
enfadado
confundido
llorar
avergonzado
sorprendido
triste
sol
estrella
jarra
camara
taza de cafe
email
beso
bombilla
amor
mal
bien
Es necesario revisar y aceptar las políticas de privacidad