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: 30 de Junio de 1.996 - Domingo

Apéndice A:
El Módulo de Portabilidad

Este Proyecto Fin de Carrera ha sido diseñado para permitir, de forma simple, su compilación en entornos diferentes. La adaptación del código a un nuevo sistema no debería suponer más de unos pocos minutos. El objetivo del módulo de portabilidad es, precisamente, facilitar al máximo esta tarea. Para ello se recurre a:

  • Definición de tipos genéricos de datos. De esta forma se pretende aislar el código de las diferentes representaciones adoptadas por los distintos compiladores existentes y las diversas arquitecturas de CPU en el mercado.

  • Rutinas de adaptación entre el formato de representación interno de datos y el formato estándar de red.

  • Todas las llamadas al sistema operativo se concentran en este módulo, así como todos los accesos al hardware.


Tipos Genéricos de Datos


int8
int16
int32

Tipos genéricos que corresponden a enteros CON SIGNO de 8, 16 y 32 bits, respectivamente. El formato de representación es complemento a dos.


uint8
uint16
uint32

Tipos genericos para enteros SIN SIGNO de 8, 16 y 32 bits.


POINTER

Puntero genérico a un tipo de datos arbitrario.


FPOINTER

Puntero a una función.


pint8
pint16
pint32

Punteros a enteros con signo de 8, 16 y 32 bits, en complemento a dos.


puint8
puint16
puint32

Punteros a enteros sin signo de 8, 16 y 32 bits.


pvoid

Puntero comodín. Puede apuntar a cualquier tipo de datos.


Rutinas de Portabilidad


void panic(puint8 cadena);

Esta rutina visualiza el mensaje contenido en "cadena" y termina la ejecución del programa. Imprime también el identificador del proceso que se estaba ejecutando cuando ocurrió el error. Utiliza la rutina siguiente.


void imprimir(puint8 cadena);

Esta rutina imprime la cadena "cadena". La salida también puede dirigirse hacia un fichero.


pvoid aloc(uint32 longitud);

Devuelve un puntero a un bloque de memoria de "longitud" bytes. Si hay algún problema retorna NULL.


void free(pvoid memoria);

Esta rutina permite liberar un bloque de memoria "memoria" previamente reservado con "aloc".


uint32 tiempo(void);

Proporciona una indicación de tiempo, en milisegundos. Dependiendo de la máquina puede indicar el tiempo transcurrido desde una fecha determinada, desde que se encendió el ordenador o el tiempo transcurrido desde el inicio del programa. La precisión de esta rutina depende del hardware subyacente. En un PC Compatible tiene una granularidad de 55 milisegundos, mientras que en un Atari es de 5 milisegundos.


void inic_disp(uint32 disp,puint8 POINTER buffer_tx,puint16 long_tx,
  puint8 POINTER buffer_rx,puint16 long_rx);

A través de esta rutina se inicializa un dispositivo físico. Está diseñada para trabajar con interfaces serie bidireccionales. El nombre del dispositivo es "disp". Los datos relevantes del mismo se almacenarán en las variables pasadas por referencia. "buffer_tx" y "buffer_rx" indican la localización de los búfferes para las rutinas de interrupción, mientras que "long_tx" y "long_rx" informan de su longitud.

Cuando se invoca, la rutina borra automáticamente ambos búfferes.


void fin_disp(uint32 disp);

Con esta función se da por finalizado el uso del dispositivo "disp". La rutina se puede llamar aunque el dispositivo no se haya inicializado previamente. Ello es utilizado de forma intensiva en la rutina "panic".


void actualiza_disp(uint32 disp,
  uint16 offset_escr_tx,puint16 offset_lect_tx,
  uint16 offset_lect_rx,puint16 offset_escr_rx);

Esta rutina actualiza los parámetros internos de los sistemas de comunicación serie por interrupciones y nos proporcionan información sobre el estado de los mismos. En "offset_escr_tx" y "offset_lect_rx" informamos de cual es nuestra situación actual. A través de "offset_lect_tx" y "offset_escr_rx" la rutina nos da a conocer el estado de las rutinas de interrupciones.


estado flujo_tx_disp(uint32 disp);

Gracias a esta rutina podemos saber si es posible insertar un byte adicional en la cola de transmisión de un dispositivo sin que ésta rebose. Aunque conociendo el tamaño del búffer pudiera parecer que esta rutina resulta innecesaria, es importante tener en cuenta la existencia de interfaces físicos con colas FIFO internas que complican notablemente la implementación. Para que el resultado de esta llamada sea fiable hay que invocar previamente "actualiza_disp".


void char_tx_disp(uint32 disp,uint8 caracter);

Esta rutina envía el carácter "caracter" a través del dispositivo "disp". Aunque podríamos transmitir toda nuestra información haciendo uso de este procedimiento, la intención es que accedamos directamente al búffer de transmisión a través de los datos proporcionados por "inic_disp". De esta forma el aumento del rendimiento es espectacular.

Dado que dichos accesos directos al búffer de transmisión son transparentes a las rutinas de interrupciones es necesario informarles periódicamente de la situación. Para ello se hace uso de "actualiza_disp". Las rutinas "flujo_tx_disp" y "char_tx_disp" son necesarias para volver a habilitar las interrupciones de transmisión si el sistema las había desconectado al terminar de transmitir los datos. La idea es utilizar estas rutinas cuando el búffer se llena o bien en el último byte de una ráfaga.


uint8 char_rx_disp(uint32 disp);

La filosofía de esta rutina es muy similar a la de la anterior. Aunque debemos acceder al búffer de recepción directamente por motivos de eficiencia, es preciso leer el último carácter recibido a través de esta rutina. De esa forma notificamos a las rutinas de interrupción que hemos hecho sitio en el búffer para que ellas, a su vez, se responsabilicen de reactivar las interrupciones, actualizar las señales de control de flujo, etc. Para un funcionamiento correcto es preciso llamar antes a "actualiza_disp".


uint32 host2net32(uint32 v);
uint16 host2net16(uint16 v);
uint32 net2host32(uint32 v);
uint16 net2host16(uint16 v);

Estas rutinas son las encargadas de convertir la representación interna del ordenador al formato universal estandarizado en "Internet".


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-PRT] Laboratorio de Comunicación de Datos
            Curso 94-95. Vigo, 16 de Marzo de 1.995
            Módulo de Portabilidad
            Alvaro Manuel Gómez Vieites
            Carlos Gabieiro Martínez
            Jose Cadavid Jáuregui
            Jesús Cea Avión

[PORTABLE]  Proyecto Global de Portabilidad para Lenguaje C
            Jesús Cea Avión
            11 de Abril de 1.990

[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