Autor
|
Tema: ¿Por que segmentacion? (Leído 4,387 veces)
|
Usuario887
Desconectado
Mensajes: 310
|
Hola, Segun Wikipedia: 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. Entiendo que el modelo de memoria segmentado puede ser mas intuitivo que un modelo totalmente lineal... sin embargo, ¿me estoy perdiendo de algo? porque precisamente intuyo que no solamente se debe a la simplicidad de utilzar segmentos sino a variedad de mas necesidades tecnicas. Sin embargo no se me ocurre ninguna. ¿alguien las conoce? y otra cosa... si es por el margen mayor de acceso a la memoria, ¿por que no usar combinatoria en vez de segmentacion? es decir, en vez de (por ejemplo): 12ABh:34CDh referenciar a 12AB*10+34CD=15F7D algo asi: 12ABh:34CDh referenciar a *calculos tediosos de combinatoria*=12AB34CD tendriamos los mismos recursos y un rango mayor de acceso a la memoria. Saludos.
|
|
|
En línea
|
|
|
|
Serapis
|
Esto viene de antiguo, de cuando la memoria era demasiado restringida. Tiene que ver simplemente con el tamaño del bus de direcciones. Como supongo que sabrás, se empezó con 4 bits, luego se saltó a 8, luego a 16, 32, 64... pero... no es así de fácil. Un microprocesador tiene 3 buses: - el bus de datos. - el bus de control. - el bus de direcciones. El bus de datos, determina el tamaño de 'palabra' que maneja la UAL... en tanto que el bus de direcciones maneja la memoria. Ha sido típico que cada salto, en realidad se haya dado (a menudo, no siempre) en 2 pasos... primero se duplicaba el tamaño del bus de direcciones y en otra se doblaba el tamaño del bus de datos. El bus de direcciones casi siempre ha precisado ser mayor que el bus de datos. Aunque la memoria estuviera limitada, otros periféricos externos, odrían tener mucho más espaico al que era preciso poder acceder. Si se usa un bus de direcciones de 16 bits, solo se puede acceder a 65536 posiciones de memoria... para los viejos micros de 8 bits (dle bus de datos), solía ser suficiente, pués empezaron teneinedo la friolera de 3-8kb. de datos... de los que además (algunos micros) para colmo, tenían una cantidad ya reservada por la ROM (caso típico de los ordenadores dirigidos al mercado doméstico. De repende se dio el salt a los 16 bits, pero 64Kb. de memoria base daban para poco, especialmente para el acceso a disco... así, sin necesidad de dotar a tod el micro de 4 líneas más a todo el chip, se añadían por 'abajo' de la nada... y así se podían direccionar ya 20 bits, que daban para 1Mb. (2^20)... El sistema se siguió usando pues era un modelo útil. por ejemplo... El sistema operativo, a menudo tiene que tratar con páginas de datos... hay muchos algoritmos, para intentar garantizar que haya memoria libre disponible junta preferentemente, esos algoritmos para hacer un uso eficiente de la memoria, precisan también compartimentar la memoria, lo mismo cuando se precisa guardar memoria a disco para liberarla y tener más memoria libre para alguna aplicación de forma puntual... Por supuesto eso complica un poco al usuario (programador)... especialmente si no entiende qué hace o porqué existe. Hoy día, yo no vería mal una paginación basada en 64Mb. de tamaño... Por aquí, algo de info adicional: https://foro.elhacker.net/programacion_visual_basic/simulador_segmentacion_paginada-t486073.0.html;msg2168899;topicseen#msg2168899
|
|
|
En línea
|
|
|
|
Usuario887
Desconectado
Mensajes: 310
|
Cito: Sea el caso del procesador 8086, el bus de datos es de 16bits, en tanto que el bus de direcciones es de 20bits. Pero los 4 bits adicionales siguen siendo los supuestos por el procesador al multiplicar por 0x10, ¿no? Entonces es una convencion historica... lo supuse, en realidad me parecia poco eficiente considerando otras posibilidades. Me atrevo a afirmar que el ser humano sacrifica su propio rendimiento por comodidad. Nuestra voluntad en contra de ella misma. Y si me permites otra pregunta, toma en cuenta las siguentes direcciones: 1234h:0004h y 1233h:0014h Calculando las direcciones: 12340h+04h=12344h y 12330h+14h=12344h Segun Wikipedia: 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. Imagina que el sistema operativo carga los datos de un proceso A en el segmento 1233h y lo marca como pertenenciente al proceso A. Luego, el segmento inmediatamente siguiente es 1234h, e imaginemos que aqui se cargan los datos de un proceso B. Si el proceso A accede a sus datos, ¿no estaria accediendo a los datos del proceso B tambien? Tiene que haber una manera de resolver esto, sin embargo no se me ocurre mas nada aparte del problema. Gracias por responder.
|
|
« Última modificación: 13 Mayo 2020, 20:19 pm por marax »
|
En línea
|
|
|
|
Serapis
|
Pero los 4 bits adicionales siguen siendo los supuestos por el procesador al multiplicar por 0x10, ¿no? No. Por eso son precisos dos registros.. Uno indica el segmento (por ejemplo CS) y el otro el desplazamiento (por ejemplo IP) Además no vale cualquier pareja de registros. Cada registro de segmento admite unos específicos. Esto tiene que ver con la arquitectura del procesador. Entonces es una convencion historica... lo supuse, en realidad me parecia poco eficiente considerando otras posibilidades. Me atrevo a afirmar que el ser humano sacrifica su propio rendimiento por comodidad. Nuestra voluntad en contra de ella misma. Bueno, es una licencia decirlo así... El que inventa algo, lo hace como considera mejor (sea mejor por la economía, por los medios disponibles o por cualquier otra razón) en ese preciso momento. Es muy fácil criticar 20, 50, ...x años después que hubiera sido mejor de esta u otra manera. Cuanto todo estaba oscuro y no había nada en lo que basarse para empezar, cualquier paso dado será el primero, si luego resulta problemático se supone que aprenderán y mejorarán. 1234h:0004h y 1233h:0014h
Calculando las direcciones:
12340h+04h=12344h y 12330h+14h=12344h
Segun Wikipedia: ... Imagina que el sistema operativo carga los datos de un proceso A en el segmento 1233h y lo marca como pertenenciente al proceso A. Luego, el segmento inmediatamente siguiente es 1234h, e imaginemos que aqui se cargan los datos de un proceso B. Si el proceso A accede a sus datos, ¿no estaria accediendo a los datos del proceso B tambien?
A estas alturas (si leíste el enlace de mi anterior mensaje) ya sabes que hay 4096 pares de combinaciones para referirse a una misma dirección, es decir se estarían refiriendo al mismo segmento. Ahora bien tu partes de una suposición (digamos) errónea... El sistema operativo, cuando asigna un segmento a un proceso, lo marca como ocupado (lleva control de ello en una estructura de datos), luego no va a asignar a otro proceso el mismo (o parcialmente el mismo) segmento. Hay muchos algoritmos para el manejo de la memoria... Cuando funcionan bien se les supone libre de dichos errores. es lo mismo que si tu tuvieras un array y en un índice guardaras tal o cual dato y más adelante por error lo sobrescribieras por otro dato, sin pretender borrar el que estaba ahí antes. Se supone que cuando ese programa salga a la luz, habrás corregido el error, tan pronto te dieras cuenta... Tiene que haber una manera de resolver esto, sin embargo no se me ocurre mas nada aparte del problema.
Básicamente se recurre a estructuras de árbol. Hay varias estrategias, te expongo brevemente algunas ideas: Al principio el árbol tiene (idealmente) toda la memoria libre, que ha particionado en x tamaño y asigna cada parte a un nodo de un árbol binario. Cada nodo tiene un estado para indicar libre u ocupado y si está ocupado cuanto está ocupado. En este árbol binario, solo los nodos terminales mantiene los datos, los nodos internos podrían considerarse como enrutadores rápidos, solo dispondran de datos muy simples que podrían (interesa que así sea) reflejar el total, pero sin disponer de las direcciones, datos que solo recáe en los nodos terminales. Luego un proceso se inicia y requiere x espacio, entonces el árbol busca un nodo que disponga de ese tamaño. Si el nodo raíz indica que ese tamaño existe, revisa si su hijo izquierdo para ver si lo contiene, si no el hijo derecho. Y así va sucesivamente descendiendo hasta el primer nodo que diga tener ese espacio libre, el nodo padre señala señala siempre el espacio libre de sus dos hijos, de modo que no hace falta explorar una rama si un padre declara que en su descendencia no hay memoria libre. El nodo terminal proporciona la dirección física donde comienza ese espacio y la cantidad disponible. Un S.O. podria asignar todo el espacio que señala que controla el nodo o bien podría asignar solo la imprescindible ocupada, con lo que partiría el nodo en dos nodos, a la derecha el nodo con la dirección y el tamaño ocupado, al que marca ocupado y a la derecha el resto de memoria que ocupa ese padre, con la dirección y cantidad libre... como se ha tomado x memoria, a cada padre subiendo va descontando ese dato de 'libre'. Si no basta un solo nodo para satisfacer la memoria requerida buscará si hay nodos contiguos con suficiente memoria libre, lo que complica la estructura, pués debe ser eficiente en cuanto a búsquedas. Pero ya sabemos que para eso basta consultar a algún padre... Una de las operaciones de este tipo de estructuras debe ser la capacidad de mover datos de un lado de la memoria a otro precisamente para unificar memoria libre dispersa. Inversamente a cuando se ocupa la memoria, cuando se libera, se accede al nodo hijo cuya memoria está contenido, se le marca libre e informa ascendentemente de la cantidad añadida. Estos algoritmos tienen que hilar muy fino, pués el rendimiento de todo el sistema puede depender de su eficacia. ...y en definitiva el S.O. no va a entregar a sendos procesos un mismo espacio de memoria. Ten en cuenta además que los procesadores de hoy día disponen de muchas más intrucciones diseñadas explícitamente para el S.O. que hace 20, 30 ó 40 años.
|
|
|
En línea
|
|
|
|
RayR
Desconectado
Mensajes: 243
|
¿Hablas de modo real o protegido? Porque es muy diferente según el caso y veo que se están mezclando los dos.
En modo real las direcciones sí son de 20 bits y se calculan multiplicando el selector de segmento por 16 (que añade 4 bits 0) para formar una dirección base de 20 bits y a esto se le suma el offset para obtener la dirección efectiva.
En modo protegido, las direcciones son de 32 bits (quitando el 80286, en el cual son de 24 bits), y aunque se sigue usando un selector de segmento y un offset, el proceso de conversión es muy diferente. En este modo, existe una tabla global de descriptores de segmento. Cada uno de estos descriptores es una estructura de 64 bits con información acerca de un segmento, como su dirección de inicio, su dirección máxima válida (que sirve para calcular su tamaño), nivel de privilegio, permisos, etc. Entonces, cuando tenemos una dirección lógica, primero se toma el selector de segmento, que en este caso hace referencia a un descriptor dentro de la tabla global; después, de dicha tabla se obtiene la dirección base del segmento; luego se le suma el offset para obtener una dirección lineal. Si no se usa paginación, esta dirección ya se refiere directamente a una dirección física de memoria. En caso de que se use paginación (que, por cierto, sólo está admitida en modo protegido) se hace una conversión adicional, que varía según el tamaño de página usado. Y, porque quizás más adelante te surja esta duda, te comento que aunque en modo protegido se puede usar un modelo de memoria plano, la segmentación sigue estando presente. La ventaja es que todo esto se realiza de forma interna y, en general, transparente al programador. Es decir, usando modelo plano, te puedes olvidar de la segmentación, y escribir programas como si no existiera.
En cuanto a lo que preguntabas sobre la memoria de los procesos, únicamente en modo protegido se ofrece protección. Para eso se puede usar tanto la segmentación como la paginación. En el caso de la primera, una forma es mediante tablas de descriptores locales. Cada tarea tiene una propia, la cual contiene únicamente los segmentos válidos para ella (aparte de los de la tabla global, que son accesibles a las tareas, siempre que los niveles de privilegio lo permitan). Todo esto podría sonar muy ineficiente, pero el procesador tiene maneras de hacer que estas verificaciones se realicen lo más rápido posible, como registros que guardan información de la tabla global y de la tarea actual, entre otras cosas
|
|
|
En línea
|
|
|
|
Serapis
|
El modo más sencillo de espantar a alguien de la programación, es llenarlo de detalles crudos en fases tempranas. Basta una explicación general... tiempo tendrá de profundizar si sigue interesado en el tema, cuando ya adquiera una base.
|
|
|
En línea
|
|
|
|
Usuario887
Desconectado
Mensajes: 310
|
El modo más sencillo de espantar a alguien de la programación, es llenarlo de detalles crudos en fases tempranas.
El sol no se posa en manos que se quemen, si te deshaces de la llama es porque realmente no te gusta el fuego. Saludos.
|
|
|
En línea
|
|
|
|
Usuario887
Desconectado
Mensajes: 310
|
tabla global de descriptores de segmento.
Si me permites otra pregunta, ¿cual fue la primera version de Windows y/o Linux que utilizo GDTs? Gracias por tu respuesta. Resolviste ademas otra duda que tambien tenia. Saludos.
|
|
|
En línea
|
|
|
|
RayR
Desconectado
Mensajes: 243
|
Si me permites otra pregunta, ¿cual fue la primera version de Windows y/o Linux que utilizo GDTs?
Bueno, considerando que las GDTs no existen en modo real, y que en el protegido no son opcionales (crear una y pasársela al procesador es requisito para siquiera iniciar este modo), la respuesta sería: la primera que corriera en este modo. En el caso de Linux, todas, desde la primera versión del kernel, lo han hecho. Con Windows no estoy seguro, pero probablemente la Windows/386. En esos tiempos Windows no era un sistema operativo, sino una interfaz gráfica encima de DOS, pero me parece que esa versión sí iniciaba el modo protegido al ejecutarse. Ya como SO propiamente dicho, todas sus versiones, NT o 9x, corrían en este modo, por lo que necesariamente usaban una GDT.
|
|
|
En línea
|
|
|
|
|
Mensajes similares |
|
Asunto |
Iniciado por |
Respuestas |
Vistas |
Último mensaje |
|
|
Ayuda con la Segmentacion de red
« 1 2 3 »
Redes
|
josl
|
25
|
62,751
|
26 Marzo 2012, 20:26 pm
por elpoetaborracho
|
|
|
Fallo de segmentación!!
Programación C/C++
|
<[(x)]>
|
6
|
3,737
|
13 Julio 2010, 06:44 am
por nicolas_cof
|
|
|
Fallo de segmentación
Programación C/C++
|
W0lFy
|
2
|
4,013
|
21 Octubre 2010, 01:09 am
por W0lFy
|
|
|
[?] Fallo de segmentación - C
Programación C/C++
|
8789poli
|
3
|
4,644
|
14 Diciembre 2010, 19:50 pm
por 8789poli
|
|
|
Fallo de segmentacion
Programación C/C++
|
_niu
|
9
|
5,458
|
29 Agosto 2011, 02:58 am
por _niu
|
|