Member of The Internet Defense League Últimos cambios
Últimos Cambios
Blog personal: El hilo del laberinto Geocaching

Desarrollo de una Herramienta Software para el Acceso a Redes TCP/IP a través de la Red Telefónica Conmutada

Última Actualización: 28 de Junio de 1.996 - Viernes

Capítulo 1:
El Módulo de Gestión de Memoria

Dadas las características de este Proyecto Fin de Carrera, en especial su funcionamiento mediante interrupciones, resulta imprescindible utilizar un módulo de gestión de memoria diseñado con determinados requisitos en mente:

  • No pueden realizarse llamadas al sistema operativo nativo debido al funcionamiento por interrupciones y al carácter TSR (Terminate and Stay Resident) de este Proyecto.

  • La reserva y liberación de memoria debe ser lo más rápida posible.

  • Debe ser posible compartir porciones de memoria entre diferentes procesos, gestionando adecuadamente el arbitraje de su liberación. De esta forma se intenta reducir al mínimo imprescindible la copia de búfferes de RAM.

  • El sistema de gestión de memoria debe posibilitar el empleo de bloques encadenados para facilitar y acelerar al máximo el procesado de las cabeceras de los protocolos involucrados.

La unidad básica de trabajo del sistema de gestión de memoria es el MBUF (búffer de memoria). Cada vez que un proceso solicita un bloque de memoria se devuelve un puntero a una estructura MBUF, que hace el papel de descriptor. En esa estructura se almacenan diversas informaciones relativas al bloque al cual corresponde, algunas accesibles y modificables por el proceso propietario y otras privadas al propio módulo de gestión de memoria.

La utilidad de dichas estructuras consiste en posibilitar la compartición de bloques de memoria entre diferentes procesos, el permitir encadenar bloques de memoria para -por ejemplo- concatenar cabeceras, y el facilitar la fragmentación de los datagramas entrantes en sus cabeceras correspondientes.

Cada MBUF define un bloque de memoria asignado. Ese bloque puede, a su vez, estar asignado a otros procesos (compartición de memoria) y formar parte de una cadena de estructuras MBUF que definen una entidad lógica. Ejemplo de ello es un datagrama compuesto por sus datos y las diversas cabeceras asociadas. Los MBUF, internamente, referencian a sus bloques de memoria mediante un puntero y una longitud. Juntos especifican una sección de memoria accesible a través de cada MBUF. Es muy importante señalar que es posible modificar ambos valores (puntero y longitud) siempre y cuando el nuevo rango accesible esté incluido en el antiguo. Es decir, siempre y cuando se mantenga la coherencia del nuevo MBUF así obtenido. Esta facilidad se utiliza intensivamente en todos los procesos para eliminar la necesidad de copias de memoria en la gestión de cabeceras.


Interfaz

El acceso a este módulo se realiza mediante llamadas a procedimientos y funciones que se ejecutan dentro del contexto del proceso actual. La unidad básica de trabajo es el MBUF (búffer de memoria), definido como una estructura con los siguientes campos:


  struct mbuf {
    puint8 datos;
    uint16 longitud;
    struct mbuf POINTER siguiente;
  };

El campo "datos" apunta al bloque referenciado por el MBUF. "longitud" indica el número de bytes accesibles utilizando este MBUF. Por último "siguiente" es un puntero a la siguiente estructura MBUF perteneciente a la misma entidad lógica (puede ser NULL). Los campos "datos" y "longitud" pueden modificarse libremente siempre que se verifique que:


  datos.viejo <= datos.nuevo < datos.viejo+longitud.viejo
  datos.nuevo+longitud.nuevo <= datos.viejo+longitud.viejo

Las condiciones anteriores garantizan que el nuevo segmento de memoria está completamente comprendido dentro del antiguo.

Por razones de comodidad se ha definido el tipo "pmbuf" como un puntero a una estructura MBUF.

Las rutinas disponibles son:


void mem_init(uint32 mem);

Esta rutina debe ejecutarse al arrancar el programa. Sirve para inicializar el módulo de gestión de memoria. No debería invocarse más de una vez a lo largo de toda la ejecución. El parámetro indica la cantidad de memoria a utilizar, en bytes.


void mem_end(void);

Esta rutina debe invocarse al finalizar el programa, para liberar la memoria reservada inicialmente.


pmbuf mem_bloc_aloc(void);

Esta rutina devuelve un puntero a una estructura MBUF. El bloque de memoria solicitado será nuevo, es decir, no compartido por ningún otro proceso, hasta que se indique lo contrario.


void mem_bloc_free(pmbuf m);

Esta rutina permite liberar un bloque de memoria, esté o no compartido por otros procesos. Si el bloque es compartido se retrasa la liberación hasta que se purgan todas sus referencias. Sólo se liberará este bloque, aunque éste pertenezca a una cadena MBUF.


void mem_free(pmbuf m);

Rutina equivalente a la anterior, pero que libera toda una cadena MBUF. Si se trata de un bloque aislado ambas llamadas son idénticas.


pmbuf mem_bloc_share(pmbuf m);

Esta llamada devuelve un puntero a una nueva estructura MBUF que que comparte la memoria con el MBUF indicado como parámetro. El nuevo MBUF no formará parte de una cadena sea cual sea el MBUF original.


pmbuf mem_share(pmbuf m);

Esta llamada permite crear una cadena compartida de bloques MBUF.


Implementación

La memoria indicada mediante "mem_init" se divide en bloques de tamaño MEM_BLOQUE (por defecto 1024 bytes). Todos los bloques asignados tienen este tamaño. No es posible solicitar tamaños diferentes, a menos que se utilice una librería extra (ver, por ejemplo, "memoria_temporal" en la librería común). Es posible, no obstante, modificar el tamaño del bloque a gestionar mediante la modificación de los campos correspondientes de las estructuras MBUF, siempre sujetos a las restricciones indicadas con anterioridad. Cuando dos o más MBUF hacen referencia al mismo bloque de memoria éste permanece asignado hasta que todos los punteros a él han sido dados de baja. En la implementación actual un bloque sólo puede ser compartido, como máximo, por 255 MBUF's diferentes. Un intento de superar dicho límite supone un error fatal en tiempo de ejecución. Dado que los datos de las estructuras MBUF pueden ser modificadas de forma dinámica por los diferentes procesos, el módulo de gestión de memoria mantiene internamente un puntero a la tabla de compartición de bloques. De esta forma se puede seguir la pista a todos los bloques asignados y compartidos aunque estos cambien de tamaño y dirección. Si no hay suficiente memoria para satisfacer una petición, se produce un error fatal en tiempo de ejecución.


Bibliografía


[LABCD]     Laboratorio de Comunicación de Datos
            Curso 94-95. Vigo, 16 de Marzo de 1.995
            Alvaro Manuel Gómez Vieites
            Carlos Gabieiro Martínez
            Jose Cadavid Jáuregui
            Jesús Cea Avión

[LABCD-MEM] Laboratorio de Comunicación de Datos
            Curso 94-95. Vigo, 16 de Marzo de 1.995
            Módulo de Gestión de Memoria
            Alvaro Manuel Gómez Vieites
            Carlos Gabieiro Martínez
            Jose Cadavid Jáuregui
            Jesús Cea Avión

[POWERNET]  Proyecto PowerNet
            Jesús Cea Avión
            Implementación de multitarea cooperativa en lenguaje C
            11 de Abril de 1.990



Python Zope ©1996 jcea@jcea.es

Más información sobre los OpenBadges

Donación BitCoin: 19niBN42ac2pqDQFx6GJZxry2JQSFvwAfS