viernes, 19 de julio de 2019

ESTRUCTURA DE LA MEMORIA SEGMENTACIÓN DE LA MEMORIA

ESTRUCTURA DE LA MEMORIA
SEGMENTACIÓN DE LA MEMORIA


Es un esquema de manejo de memoria mediante el cual la estructura del programa refleja su división lógica; llevándose a cabo una agrupación lógica de la información en bloques de tamaño variable denominados segmentos. Cada uno de ellos tienen información lógica del programa: subrutina, arreglo, etc. Luego, cada espacio de direcciones de programa consiste de una colección de segmentos, que generalmente reflejan la división lógica del programa.

La 
segmentación permite alcanzar los siguientes objetivos:
1.        Modularidad de programas: cada rutina del programa puede ser un bloque sujeto a cambios y recopilaciones, sin afectar por ello al resto del programa.
2.      Estructuras de datos de largo variable: ejm. Stack, donde cada estructura tiene su propio tamaño y este puede variar.
3.       Protección: se puede proteger los módulos del segmento contra accesos no autorizados.
4.      Comparación: dos o más procesos pueden ser un mismo segmento, bajo reglas de protección; aunque no sean propietarios de los mismos.
5.      Enlace dinámico entre segmentos: puede evitarse realizar todo el proceso de enlace antes de comenzar a ejecutar un programa. Los enlaces se establecerán solo cuando sea necesario.


Ventajas de la segmentación
El esquema de segmentación ofrece las siguientes ventajas:
·         El programador puede conocer las unidades lógicas de su programa, dándoles un tratamiento particular.
·         Es posible compilar módulos separados como segmentos el enlace entre los segmentos puede suponer hasta tanto se haga una referencia entre segmentos.
·         Debido a que es posible separar los módulos se hace más fácil la modificación de los mismos. Cambios dentro de un módulo no afecta al resto de los módulos.
·         Es fácil el compartir segmentos.
·         Es posible que los segmentos crezcan dinámicamente según las necesidades del programa en ejecución.
·         Existe la posibilidad de definir segmentos que aún no existan. Así, no se asignará memoria, sino a partir del momento que sea necesario hacer usos del segmento. Un ejemplo de esto, serían los arreglos cuya dimensión no se conoce hasta tanto no se comienza a ejecutar el programa. En algunos casos, incluso podría retardar la asignación de memoria hasta el momento en el cual se referencia el arreglo u otra estructura de dato por primera vez.


Desventajas de la segmentación
·         Hay un incremento en los costos de hardware y de software para llevar a cabo la implantación, así como un mayor consumo de recursos: memoria, tiempo de CPU, etc.
·         Debido a que los segmentos tienen un tamaño variable se pueden presentar problemas de fragmentación externas, lo que puede ameritar un plan de reubicación de segmentos en memoria principal.
·         Se complica el manejo de memoria virtual, ya que los discos almacenan la información en bloques de tamaños fijos, mientras los segmentos son de tamaño variable. Esto hace necesaria la existencia de mecanismos más costosos que los existentes para paginación.
·         Al permitir que los segmentos varíen de tamaño, puede ser necesarios planes de reubicación a nivel de los discos, si los segmentos son devueltos a dicho dispositivo; lo que conlleva a nuevos costos.
·         No se puede garantizar, que, al salir un segmento de la memoria, este pueda ser traído fácilmente de nuevo, ya que será necesario encontrar nuevamente un área de memoria libre ajustada a su tamaño.
·         La compartición de segmentos permite ahorrar memoria, pero requiere de mecanismos adicionales da hardware y software.
“Estas desventajas tratan de ser minimizadas, bajo la técnica conocida como Segmentación paginada”.

Segmentación Paginada

Paginación y segmentación son técnicas diferentes, cada una de las cuales busca brindar las ventajas enunciadas anteriormente.

Para la segmentación se necesita que estén cargadas en memoria, áreas de tamaños variables. Si se requiere cargar un segmento en memoria; que antes estuvo en ella y fue removido a memoria secundaria; se necesita encontrar una región de la memoria lo suficientemente grande para contenerlo, lo cual no es siempre factible; en 
cambio "recargar" una página implica solo encontrar un merco de página disponible.

A nivel de paginación, si quiere referenciar en forma cíclicas n páginas, estas deberán ser cargadas una a una generándose varias interrupciones por fallas de páginas; bajo segmentación, esta página podría conformar un solo segmento, ocurriendo una sola interrupción, por falla de segmento. No obstante, si bajo segmentación, se desea acceder un área muy pequeña dentro de un segmento muy grande, este deberá cargarse completamente en memoria, desperdiciándose memoria; bajo paginación solo se cargara la página que contiene los ítems referenciados.
Puede hacerse una combinación de segmentación y paginación para obtener las ventajas de ambas. En lugar de tratar un segmento como una unidad contigua, este puede dividirse en páginas. Cada segmento puede ser descrito por su propia tabla de páginas.

Los segmentos son usualmente múltiplos de páginas en tamaño, y no es necesario que todas las páginas se encuentren en memoria principal a la vez; además las páginas de un mismo segmento, aunque se encuentren contiguas en memoria virtual; no necesitan estarlo en memoria real.

Las direcciones tienen tres componentes: (s, p,d), donde la primera indica el número del segmento, la segunda el número de la página dentro del segmento y la tercera el desplazamiento dentro de la página. Se deberán usar varias tablas:
·         SMT (tabla de mapas de segmentos): una para cada proceso. En cada entrada de la SMT se almacena la información descrita bajo segmentación pura, pero en el campo de dirección se indicará la dirección de la PMT (tabla de mapas de páginas) que describe a las diferentes páginas de cada segmento.
·         PMT (tabla de mapas de páginas): una por segmento; cada entrada de la PMT describe una página de un segmento; en la forma que se presentó la página pura.
·         TBM (tabla de bloques de memoria): para controlar asignación de páginas por parte del sistema operativo.
·         JT (tabla de Jobs): que contiene las direcciones de comienzo de cada una de las SMT de los procesos que se ejecutan en memoria.
En el caso, de que un segmento sea de tamaño inferior o igual al de una página, no se necesita tener la correspondiente PMT, actuándose en igual forma que bajo segmentación pura; puede arreglarse un bit adicional (S) a cada entrada de la SMT, que indicara si el segmento esta paginado o no.

Ventajas de la segmentación paginada

El esquema de segmentación paginada tiene todas las ventajas de la segmentación y la paginación:
·         Debido a que los espacios de memorias son segmentados, se garantiza la facilidad de implantar la compartición y enlace.
·         Como los espacios de memoria son paginados, se simplifican las estrategias de almacenamiento.
·         Se elimina el problema de la fragmentación externa y la necesidad de compactación.
Desventajas de la segmentación paginada
·         Las tres componentes de la dirección y el proceso de formación de direcciones hacen que se incremente el costo de su implantación. El costo es mayor que en el caso de segmentación pura o paginación pura.
·         Se hace necesario mantener un número mayor de tablas en memoria, lo que implica un mayor costo de almacenamiento.

jueves, 18 de julio de 2019

Pila,retorno,etc

PILA
Una pila es una estructura de datos en la que el modo de acceso a sus elementos es de tipo LIFO (del inglés Last in First Out, último en entrar, primero en salir) que permite almacenar datos.
Se cuenta con dos operaciones básicas: apilar (push), que coloca un objeto en la pila, y su operación inversa, retirar (o desapilar, pop), que retira el último elemento apilado.
En cada momento sólo se tiene acceso a la parte superior de la pila, es decir, al último objeto apilado (denominado TOS, Top of Stack  en inglés).
Para entender mejor su funcionamiento podemos usar la analogía de una pila de platos, el primero que ponemos encima de la pila de platos es el primer plato que sacamos.
La pila de llamadas es la zona de memoria que utiliza esta estructura de datos para almacenar información sobre las llamadas a funciones. Cuando empieza la ejecución del programa, la pila está vacía. En cada llamada a una función o subrutina, en la pila se almacena:
1.        La dirección de memoria a la siguiente instrucción de código donde debe retornar despúes de ejecutarse la función.
  1. Los datos pasados como parámetros a la función.
  2.  Las variables locales utilizadas por la función.
  3. i la función devuelvo algún valor también lo almacena en la pila.
  4. Vamos a ver un ejemplo con un trozo de código en C#.


Ejemplo de Pila:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
#include <iostream.h>
#include <conio.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>

struct pilas
{
int d;
pilas *a;
}*c,*e;

void menu(void);
void ingresar(void);
void sacar (void);
void actualizar_pila(void);

main()
{
menu();
}
void menu(void)
{
int y,opc;
 for(;;)
 {
 cout<<"\n1. Ingresar datos";
 cout<<"\t2. Sacar datos";
 cout<<"\t0. Terminar";
 cout<<"\n Ingrese opcion: ";cin>>opc;
 switch(opc)
 {
 case 1:
 ingresar();
 break;
 case 2: sacar();
 break;
 case 0: exit(1);
 default: cout<<"\n Opcion no valida!!"; break;
 }
actualizar_pila();
cout<<"\n\nOprima una tecla para continuar";
getch();
 }
}

void ingresar (void)
{
 if(!c)
 {
 c=new(pilas);
 cout<<"Ingrese elemento: ";
 cin>>c->d;
 c->a=NULL;
 return;
 }

 e=new(pilas);
 cout<<"\nIngrese elemento: ";
 cin>>e->d;
 e->a=c;
 c=e;
}

void sacar(void)
{
 if(!c)
 {
 cout<<"\n\nNo hay elementos!!";
 return;
 }

 e=new(pilas);
 e=c;
 cout<<"\n\nElemento eliminado: " <<e->d;
 c=e->a;
 delete(e);

}
void actualizar_pila(void)
{
 int y=2,i,ca=0;
 e=c;
 while(e)
 {
 ca++;
 e=e->a;
 }
for(i=0;i<=ca;i++)
 {
 cout<<" ";
 }
 //muestro lo que tiene la pila!!
 i=0;
 e=c;
 while(e)
 {
 cout<<"\n";
 cout<<++i<<" - "<<e->d;
 e=e->a;
 }
}

RETORNO
Las funciones con retorno son muy parecidas a las funciones sin retorno, pero su diferencia radica en para qué se utilizan.
Las funciones con retorno crean un “mini-programa” que se encarga de obtener, preparar o modificar una variable. La función con retorno nos devuelve ese valor justo cuando se lo pidamos, sin tenerle que decir una y otra vez al programa como obtener ese dato que necesitamos. Un ejemplo podría ser una función que se encargue de mapear el valor del potenciómetro y después retorne el valor ya mapeado del mismo componente, o también se podría hacer una función que según la distancia que viera el sensor de ultrasonidos te dijera si estás más o menos cerca del objeto que tienes delante.
Estas variables con las que jugamos en nuestras funciones con retorno pueden ser de cualquier tipo: numéricas, de texto o incluso vectores
Ejemplo
Veamos ahora las funciones que devuelven un valor, pueden ser del tipo que queramos. En este caso hagamos la misma función "Suma", pero ahora va a devolver un valor, que será el resultado de la suma de los dos números que recibe por parámetro.

Quedaría de esta forma:


De esta forma la función cambia un poco. Lo primero es que ahora no es "void", ya que si devuelve un valor en vez de "void" ponemos el tipo de dato que devolverá la función, en este caso un número entero, por lo tanto "int".
Dentro de la función, hacemos la suma de ambos números y la guardamos en una variable llamada "r". Para devolver el valor escribimos la cláusula "return", por lo tanto, esta función devolverá el resultado de la suma de ambos números, que está en la variable "r".

Parámetro y Argumentos defunciones
Las palabras parámetro y argumento, aunque de significado similar, tiene distintas connotaciones semánticas: Se denominan parámetros los tipos declarados en el prototipo (que deben corresponder con los declarados en la definición). Cuando se realiza una llamada a la función, los "valores" pasados se denominan argumentos. A veces se utilizan también las expresiones argumentos formales, para los parámetros y argumentos actuales para los valores pasados.
La sintaxis utilizada para la declaración de la lista de parámetros formales es similar a la utilizada en la declaración de cualquier identificador.  A continuación, se exponen varios ejemplos:
int func(void) {...}                  // sin parámetros
inf func() {...}                      // ídem.
int func(T1 t1, T2 t2, T3 t3=1) {...} // tres parámetros simples,
                                      // uno con argumento por defecto
int func(T1* ptr1, T2& tref) {...}    // los argumentos son un puntero y
                                      // una referencia.
int func(register int i) {...}        // Petición de uso de registro para
                                      // argumento (entero)
int func(char* str,...) {...}         /* Una cadena y cierto número de otros
             argumentos, o un número fijo de argumentos de tipos variables */


  Los argumentos son siempre objetos. Sus tipos pueden ser: escalares; estructuras; uniones, o enumeraciones; clases definidas por el usuario; punteros o referencias a estructuras y uniones, o punteros a funciones, a clases o a matrices. El tipo void está permitido como único parámetro formal. Significa que la función no recibe ningún argumento.

Variable Locales
Una variable local es aquella cuyo ámbito se restringe a la función que la ha declarado se dice entonces que la variable es local a esa función. Esto implica que esa variable sólo va a poder ser manipulada en dicha sección, y no se podrá hacer referencia fuera de dicha sección. Cualquier variable que se defina dentro de las llaves del cuerpo de una función se interpreta como una variable local a esa función.
Cuando una variable x es local a una función func1, significa que la función func1 es la propietaria de dicha variable, y puede acceder a ella y modificarla. Si cualquier otra función del programa necesita conocer el valor de la variable x, es la función func1 la que debe transferir el valor de x a través del paso de argumentos en la llamada a la función. Si además esta función desea modificar el valor de dicha variable, entonces tendrá que devolver el nuevo valor a func1, y será func1 quien se encargue de asignar el valor devuelto a su variable x.



ESTRUCTURA DE LA MEMORIA SEGMENTACIÓN DE LA MEMORIA

ESTRUCTURA DE LA MEMORIA SEGMENTACIÓN  DE LA MEMORIA Es un esquema de manejo de memoria mediante el cual la  estructura  del prog...