8QLYHUVLGDG3ROLWpFQLFDGH0DGULG 'HSDUWDPHQWRGH$UTXLWHFWXUD\7HFQRORJtDGH6LVWHPDV,QIRUPiWLFRV FACULTAD DE INFORMÁTICA Trabajo de Doctorado Manejador de tipo módulo para la SCC-8530 en LINUX Alumno: Jorge OCÓN ALONSO Profesor: Juan ZAMORANO FLORES Resumen En el presente documento se describe el desarrollo de un manejador para una tarjeta de comunicaciones serie en LINUX. Este desarrollo ha sido utilizado en proyectos reales en sistemas que actualmente están funcionando. El manejador objeto de esta práctica está actualmente funcionando en sistemas de tiempo real (equipos de FRQFHQWUDGRUHV GHHVWDFLyQ) en los trenes de Buenos Aires.(TBA). Palabras clave Manejador, LINUX, Entradas y Salidas, RS-232 $JRVWR '$76,830 F.I. t Campus de Montegancedo t Boadilla del Monte t 28660 Madrid t ESPAÑA t Tel: + 34 91 3367387 t Fax: + 34 91 3367373 t http://www.fi.upm.es/ ,1752'8&&,21 48((6810$1(-$'25" /$6&&'(=,/2* /2602'8/26',1$0,&26 ,16(5&,Ï1'(6,167$/$&,21'(/.(51(/ 86$1'2(/0$1(-$'25 $1$/,6,6'(/&2',*25(/$7,92$/$//$0$'$,2&7/ CONCLUSIONES Manejador de tipo Módulo para la SCC-8530 en LINUX Trabajo de doctorado ,1752'8&&,21 Como es sabido, Linux es un sistema operativo multitarea diseñado por Linus Torvalds y un equipo de colaboradores siguiendo estándares 326,;. Aunque externamente y a nivel de programación ofrece un interfaz tipo 81,;, Linux ha sido reescrito totalmente de nuevo, por lo que el código fuente está protegido por la licencia *18, lo que permite a cualquier persona disponer del código fuente y utilizarlo de forma totalmente gratuita. Esto, que de por sí constituye un gran atractivo para un sistema operativo de cara a posibles desarrollos, es tan solo una más de sus cualidades. Otros sistemas operativos (0LQL[, por ejemplo, del cual /LQX[ heredó parte del kernel) fueron también desarrollados como sistemas libres, pero no llegaron a tener la fiabilidad, la eficiencia en el uso de recursos ni la difusión de /LQX[. En este sentido, es un hito en la historia de la Informática que merece ser reconocido, reconocimiento que se hizo público al ser premiado como ³6LVWHPD RSHUDWLYR GHO DxR ´ por ,QIRZRUOG. Aunque originalmente diseñado para el mundo de los Pcs compatibles, que es el entorno de mayor difusión, existen versiones de /LQX[ para diversas plataformas: 63$5& de 6810,&526<67(06 $/3+$ de '(&, versiones para procesadores 0RWRUROD, etc... Debido a que es software libre,, y a que estamos hablando del sistema operativo que probablemente mejor gestiona los recursos del PC actualmente, ha tenido gran difusión no sólo en entornos universitarios, sino en entornos profesionales. Hoy en día, un 30% de los servidores de Internet (Internet Sites) son PC que corren /LQX[ como sistema operativo. En torno al proyecto /LQX[ se han desarrollado paquetes de software, algunos de los cuales son sencillamente versiones portadas de otros desarrollos de *18, y otros muchos colaboraciones que se venden de forma semi-gratuita. También existen varias compañías que venden distribuciones de /LQX[ (RedHat, Debian, Slackware), y otras se dedican a dar soporte del sistema. En general, /LQX[ ha proporcionado el acceso de forma gratuita a un sistema operativo (81,;) que estaba reservado a unos pocos. En todo caso, el proyecto /LQX[ constituye una aportación sobresaliente al desarrollo del software libre, y pese a no contar con una firma que lo soporte, la difusión de /LQX[ es cada vez mayor, tanto en ambientes universitarios como profesionales. Esta práctica explica el desarrollo de un manejador para una tarjeta de comunicaciones serie en /LQX[. Este desarrollo ha sido utilizado en proyectos reales en sistemas que actualmente están funcionando. Naturalmente, no hubiera sido posible este desarrollo sin la existencia del software libre, y en particular sin la existencia de Internet. 1 (1) Este galardón fue concedido a la distribución RED-HAT. ZZZGDWVLILXSPHV 3DJ Jorge OCÓN ALONSO Tutor: Juan Zamorano <[email protected]> Sinceramente espero que el espíritu del libre intercambio de ideas y proyectos, y la colaboración desinteresada entre ingenieros de todo el mundo vaya en aumento. Es algo de lo que toda la sociedad en su conjunto, y los desarrolladores en particular, se benefician. 3DJ ZZZGDWVLILXSPHV Manejador de tipo Módulo para la SCC-8530 en LINUX Trabajo de doctorado 48((6810$1(-$'25" Los sistemas operativos clásicos (no aquellos específicamente diseñados para tiempo real), establecen una frontera clara entre el.(51(/ del sistema operativo, que gestiona los recursos (memoria, tiempo de &38, escritura y lectura en dispositivos, etc... ) y el resto de los procesos, procesos de usuario que generalmente trabajan con memoria virtual, acceden a los dispositivos mediante el sistema operativo, y son periódicamente puestos en ejecución y ‘swapped out’, es decir, hibernados por el kernel, que distribuye la &38 entre los distintos procesos, de forma que el resultado sea un aparente procesamiento en paralelo de varios procesos. En este sentido, podriamos decir que existen básicamente dos tipos de software: el kernel, que reside permanentemente en la memoria, y el resto de los procesos, cuya ejecución es controlada y manejada por el kernel. Este esquema ha demostrado tener muchas ventajas, puesto que aquellos procesos que intentan acceder a direcciones de memoria ajenas son inmediatamente detectados por el kernel, y literalmente ‘expulsados’ del sistema. Como el acceso a los recursos se realiza a través del kernel, éste puede detectar inter-bloqueos, llamadas con parámetros erróneos, y en general, cualquier error de un proceso se puede aislar de forma que no tenga consecuencias fatales para el conjunto del sistema. Cualquiera que haya programado en 06'26 (que no sigue en absoluto este esquema) y un sistema multitarea como 906 ó 81,; ha podido percatarse de esta diferencia: en 06'26, un programa puede estar accediendo a cualquier posición de memoria tanto para lectura como para escritura, y no se detecta una escritura en una posición de memoria ajena a no ser que provoque una caída del programa (lo que en la mayoría de los casos genera una caída de todo el sistema). En 906 ó 81,;, por el contrario, no ocurre esto, se detecta y se expulsa de ejecución al proceso que realiza un acceso a zonas de memoria ajenas, con lo que se facilita su depuración. Esto constituye además una buena protección contra los virus informáticos, que siempre intentan acceder a los recursos del sistema de forma inadvertida. En sistemas más recientes se ha incorporado un tercer tipo de proceso, denominado µSURFHVRGHWLHPSRUHDO¶, que está a medio camino entre la concepción de proceso clásica y el propio kernel. Estos procesos tienen la posibilidad de poder fijar plazos de tiempo muy cortos (en torno a los 10 milisegundos) para ser despertados por el kernel. En otros sistemas se permite bajo ciertas condiciones que los procesos accedan a posiciones de memoria real utilizando llamadas al sistema específicamente diseñadas para esto (3) Estas extensiones son en realidad un intento de los fabricantes de sistemas operativos de permitir que un proceso pueda cumplir con requisitos de tiempo real de forma efectiva, sin que sea preciso para esto implementar un manejador. Los manejadores son, como su nombre indica, aquellas partes del kernel específicamente diseñadas para el manejo de determinados recursos (p. ej. una tarjeta de comunicaciones, el disco, la unidad &'520, una tarjeta Ethernet, etc... ). Incorporan toda la heurística del dispositivo específico que controlan, y naturalmente, son muy dependientes del hardware: un manejador siempre está asociado al hardware que controla, y una sustitución del hardware va asociada generalmente a una sustitución del manejador, salvo que el nuevo hardware presente un interfaz compatible. ZZZGDWVLILXSPHV 3DJ Jorge OCÓN ALONSO Tutor: Juan Zamorano <[email protected]> Al formar parte del kernel, los manejadores se distinguen por completo del software de los procesos de usuario: No hacen llamadas al sistema operativo (puesto que son parte de él), sino que en su lugar, utilizan una serie de rutinas del propio sistema operativo que les permiten reservar memoria del kernel, acceder a memoria real, bloquear o liberar las interrupciones de la &38, leer o escribir vectores de interrupción, fijar plazos de tiempo muy breves (incluso por debajo de los 10 milisegundos) y acceder a la memoria virtual de un proceso, entre otras. Estas rutinas no están disponibles para los procesos normales, y son específicas del sistema operativo, por lo que lo primero que debe de hacer un programador de un manejador es familiarizarse con esta librería de rutinas del sistema. Uno no dispone de las rutinas típicas de librería para sacar datos por pantalla ó leer del teclado, por lo que la depuración del manejador constituye una experiencia diferente a la programación tradicional. Estas ventajas frente a procesos de usuario en cuanto a accesibilidad de recursos tienen a la vez el inconveniente de la fiabilidad: un manejador que se comporte de forma errónea puede perfectamente bloquear por completo el sistema operativo, causando una caida general de todo el sistema, con los peligros que ello conlleva (perdida de ficheros, necesidad de reinstalar todo el sistema operativo de nuevo, etc... ). Esto es una dificultad añadida para el desarrollo de los manejadores, que hace que muchos programadores se planteen el desarrollo de manejadores con cautela, y que se opte muchas veces por utilizar un proceso de tiempo real allí donde sea posible en lugar de un manejador. Existe un conjunto de puntos de entrada al manejador. Estos puntos de entrada son hebras de código que el sistema operativo se encarga de activar cuando un proceso usuario realiza una llamada al sistema operativo relacionada con el dispositivo del manejador. Así por ejemplo cuando un proceso usuario solicita el envío de un paquete a través de la red Ethernet de una máquina, existirá una zona de código en el manejador de la tarjeta Ethernet que se activará, para hacer posible el envio de dicho paquete, enviando los comandos precisos al dispositivo hardware a fín de que físicamente envíe la trama correspondiente. Estos puntos de entrada pueden clasificarse de forma genérica como: 3DUD DFFHGHU DO GLVSRVLWLYR Mediante el cual el proceso comunica al manejador que desea acceder al dispositivo. El manejador puede así permitir el acceso, realizando la asociación entre proceso y dispositivo, lo que le permite saber en todo momento cual o cuales de los procesos están utilizando un dispositivo determinado. En 81,;, esta es la llamada RSHQ a un manejador. 3DUD OLEHUDU HO GLVSRVLWLYR El proceso comunica asi al manejador que ha finalizado el acceso al dispositivo, con lo cual el manejador actualiza su tabla de correspondencias entre procesos/dispositivos. A efectos el proceso deja de estar asociado al dispositivo en cuestión, y el dispositivo queda libre para ser utilizado por cualquier proceso en adelante. En 81,; esto se traduce en una llamada FORVH al manejador. (VFULWXUD Para almacenar, o enviar la información. En 81,;, son accesos tipo ZULWH. 3DJ ZZZGDWVLILXSPHV Manejador de tipo Módulo para la SCC-8530 en LINUX Trabajo de doctorado /HFWXUD Leer o recibir la información del dispositivo. En 81,;, son accesos tipo UHDG 3DUDPHWUL]DU HO GLVSRVLWLYR Cambiar velocidad, Fijar paridad, especificar protocolos, cambiar modo funcionamiento. Se realizan mediante llamadas LRFWO 2EWHQHUHOHVWDGRGHOGLVSRVLWLYR Obtener estadísticas. También son llamadas LRFWO aunque existen algunas específicas. Aunque forman parte del kernel, en 81,;, el interfaz para los procesos de usuario del kernel es un fichero (siguiendo la filosofía de 81,;). El proceso que utiliza el manejador lo abre mediante una llamada RSHQ contra este fichero, y obtiene un identificador, que utiliza en las siguientes llamadas. Finaliza el acceso con una llamada a FORVH. Este tratamiento es común para todos los sistemas 81,;. Los manejadores en 81,;se clasifican en dos grandes grupos: 0DQHMDGRUHVGHPRGRFDUiFWHU 0DQHMDGRUHVGHPRGREORTXH Estos dos grandes grupos se diferencian en el modo en que procesan la información: en un manejador de tipo carácter la información se transfiere byte a byte, es decir, tanto las lecturas como las escrituras se hacen de carácter en carácter individualmente. En los manejadores de tipo bloque tanto las lecturas como las escrituras se realizan por bloques o conjuntos de varios caracteres. Un mismo dispositivo físico (p.ej. la unidad de cinta) puede tener dos manejadores diferentes de tipo bloque y de tipo carácter. La elección de uno u otro por parte del proceso se realizará siguiendo criterios de eficiencia, en función de sus necesidades. Un manejado de tipo bloque puede permitir una mayor eficiencia en las lecturas o escrituras, transfiriendo información de forma más rápida. Un manejador de tipo caracter puede permitir al proceso trabajar con mayor grado de precisión en las lecturas y/o escrituras. Los manejadores en 81,; tienen dos números asociados llamados mayor y menor (PDMRU and PLQRU). El número mayor es el que indica la versión del manejador en cuestión. Permite detectar cambios de versión del manejador en el kernel, lo que es muy importante puesto que una llamada a una función no soportada podria causar la caída de todo el sistema. El numero menor identifica al dispositivo de forma unívoca (en sistemas 6&6,, por ejemplo, el numero menor identifica la dirección 6&6, del dispositivo en cuestión), de forma que el mismo software del manejador se utilice para todos los dispositivos de ese tipo que haya en la máquina. En los sistemas ´Plug-and-play´ actualmente en uso, al arrancar el sistema los manejadores detectan automáticamente los dispositivos de su tipo que hay en la máquina y los inicializan. Esto, que sin duda es una ventaja de cara a posibles reconfiguraciones del sistema, presenta una dificultad añadida para el programador, puesto que la rutina de detección del hardware debe de ser diseñada cuidadosamente. ZZZGDWVLILXSPHV 3DJ Jorge OCÓN ALONSO Tutor: Juan Zamorano <[email protected]> Generalmente esta rutina accede a direcciones de memoria y/o vectores de interrupción que utiliza el dispositivo hardware en el momento del arranque. Si el acceso provocase una interrupción no contemplada por el kernel (lo que puede ocurrir dado que en ese momento no se sabe aún la configuración del sistema), podríamos encontrarnos con una caída general del sistema en el momento del arranque. De ahí que la rutina de detección deba de estar diseñada cuidadosamente. Los manejadores están generalmente incluidos en el kernel del sistema, formando parte del mismo. Sin embargo, en algunos sistemas operativos (como en /LQX[), existe la posibilidad de que existan como módulos independientes que se carguen dinámicamente. Para ello es necesario que exista un cargador (ORDGHU) de módulos del kernel, que se encarga de insertar el módulo en el momento en que se solicita y quitarlo del kernel cuando sea preciso. Esto presenta la ventaja de que sólo se carguen los manejadores de los dispositivos existentes, con lo cual el tamaño del kernel se ve tremendamente reducido. El tamaño del kernel es importante puesto que reside por completo en la memoria y por tanto la memoria real disponible para el sistema en ejecución es la diferencia entre toda la memoria disponible y el tamaño del kernel. Un kernel muy pequeño deja mucha memoria libre. Un kernel excesivamente grande puede producir un trashing constante del sistema. (Un kernel muy grande puede llegar a los 2Mb en /LQX[, mientras que un kernel pequeño puede tener menos de 640k). Mas adelante nos extenderemos en detallar en qué consiste un manejador que se carga dinámicamente,. El manejador objeto de esta practica es un manejador de tipo carácter para una tarjeta de comunicaciones síncrona basada en el chip Serial &RPPXQLFDWLRQV&RQWUROOHU 6&& de Zilog para comunicaciones síncronas y asíncronas. Aunque puede ser configurado en modo asíncrono, el manejador está especialmente diseñado para comunicaciones síncronas de tramas 6'/& +'/&. El manejador está basado en un manejador que obtuve vía Internet para comunicación $; para una tarjeta similar, aunque ha sido modificado por completo y ampliado. En este sentido, puede decirse que la labor realizada ha sido una labor de ingeniería inversa, de averiguar cómo funciona un manejador existente para, a partir de ahí, ampliarlo y adaptarlo a mis necesidades específicas. Agradezco a Joerg Reuter ([email protected]) el haber puesto este software a disposición de la comunidad internacional. /$6&&'(=,/2* A diferencia de la 8$57 , que es la utilizada en los ordenadores personales compatibles para las comunicaciones serie, la serie =LORJ permite las comunicaciones síncronas además de asíncronas. Esto le hace particularmente útil para comunicaciones síncronas de tipo 6'/&+'/&/$3%;, con interfaces de tipo 56 y/o 56. El dispositivo permite la generación automática e inserción del CRC en emisión, el cálculo del CRC en recepción, trabajar con reloj externo ó interno de forma independiente tanto en emisión como recepción, inserción automática de ceros en comunicaciones síncronas, trabajar en modo NRZ/NRZI y, en general, configurarse en casi todos los modos posibles de comunicaciones síncronas conocidos. Esto unido a 3DJ ZZZGDWVLILXSPHV Manejador de tipo Módulo para la SCC-8530 en LINUX Trabajo de doctorado sus capacidades para comunicaciones asíncronas, lo hace ideal para comunicaciones serie hasta 19200bps. El modelo es compatible con la USART 8251 de Intel. Aunque no es el caso de esta practica, este dispositivo puede trabajar en modo DMA, transfiriendo ó recibiendo bloques de información directamente de/a memoria. Sin utilizar las capacidades de DMA, el chip entrega una interrupción al sistema por cada byte transmitido ó recibido. Esto hace que trabajar a más de 19200bps pueda perjudicar al sistema por una sobrecarga de interrupciones (piénsese que, por ejemplo, a 19200 bps se recibe una interrupción cada 416 microsegundos, 208 microsegundos de media en )XOOG~SOH[). Esto es un factor crítico a la hora de recibir o transmitir datos puesto que si el sistema no es capaz de procesar interrupciones a esta velocidad, la 86$57 guarda los caracteres recibidos en un buffer interno de pocos caracteres (antiguamente eran sólo 3, en versiones posteriores se han ampliado a 10). El buffer interno se va vaciando conforme el sistema lee los caracteres recibidos en interrupciones sucesivas. Si en la 86$57 se llena el buffer de recepción por no haber podido procesar el sistema las interrupciones a suficiente velocidad, se produce un error de RYHUUXQ: la 86$57 nos informa de la pérdida de uno ó mas caracteres en recepción. De forma idéntica, en transmisión, la 86$57 genera una interrupción cada vez que dispone de un buffer libre para transmisión de un carácter. Si expira el tiempo de transferencia de un carácter y no hay caracteres para transmitir, se produce un error de underrun: la 86$57 nos informa de que, debido a que no ha podido enviar caracteres lo suficientemente rápido, la trama a enviar no ha podido ser transmitida. Estos dos errores (overrun en recepción y XQGHUUXQ en transmisión) son típicos en las comunicaciones síncronas. Cuando la velocidad de proceso es inferior a la de transmisión/recepción de datos. Aunque la velocidad de proceso de las &38s actuales se ha multiplicado por cuatro en los ultimos cinco años, el problema anterior se manifiesta con velocidades superiores a 19200 bps y varios canales trabajando simultáneamente, lo que hace poco aconsejable el utilizar este manejador para más de 19200 bps. No obstante, las líneas para las que fue diseñado no precisan de una velocidad superior a 19200 bps, por lo que esta no puede considerarse una restricción preocupante. Sin embargo, dejo abierta la posibilidad de que alguien modifique el manejador para que utilice DMA, lo que permitiría en el futuro velocidades muy superiores. La 86$57 es un dispositivo de comunicaciones serie programable mediante registros. Los registros se subdividen en 3 registros de lectura y 15 registros de escritura. Para leer o escribir un registro se realiza una operación binaria: primero se selecciona el registro y luego se lee o se escribe en él. El tiempo que media entre la selección del registro y la lectura ó escritura es también un factor crítico: si se excede un tiempo dado ó se realiza antes de tiempo la segunda operación la selección del registro queda anulada, y el resultado es generalmente una lectura ó escritura sobre el registro 0, que puede desprogramar por completo la 86$57. Este es un inconveniente añadido puesto que el mismo código puede funcionar o no dependiendo de la velocidad del procesador. /LQX[ facilita la independencia del procesador con una rutina del kernel, XGHOD\que permite retardar en microsegundos la ejecución del código. Una de las labores del kernel al arrancar es detectar la velocidad del procesador. De este modo, la rutina XGHOD\ nos da un retardo en microsegundos independientemente del procesador en que nos encontremos. Esta es una utilidad de /LQX[ que facilita enormemente al programador el ZZZGDWVLILXSPHV 3DJ Jorge OCÓN ALONSO Tutor: Juan Zamorano <[email protected]> desarrollo de manejadores, pues permite disponer de una gran precisión en el tiempo a la hora de mandar comandos a un dispositivo. Como dijimos anteriormente, gran parte de la dificultad de un manejador reside en el conocimiento de como funcionan las librerías de rutinas del kernel. Estas representan el modo de interaccionar con el sistema operativo, de modo que sin ellas el manejador seria inviable. En el siguiente capítulo, comentaremos en qué consiste un módulo que se cargue dinámicamente en el kernel, y cómo se consigue hacer esto en Linux. Despues comentaremos la forma en que el manejador se inserta en el kernel, para pasar después a comentar cada uno de los puntos de entrada (llamadas al sistema) que puede realizar el manejador. 3DJ ZZZGDWVLILXSPHV Manejador de tipo Módulo para la SCC-8530 en LINUX Trabajo de doctorado /2602'8/26',1$0,&26 En UNIX, existen dos formas diferentes de implementar un manejador: de tipo modulo o como parte del sistema operativo. El diseño del kernel de /LQX[ es similar al de los sistemas UNIX clásicos: arquitectura monolítica con sistemas de ficheros, manejadores y un conjunto de elementos software que estan enlazados estáticamente en el propio kernel para que los utilice en el arranque. El uso de módulos que se cargan dinámicamente permite escribir partes del kernel como objetos independientes. Comentare a continuación los detalles relativos a la instalación de un módulo en el kernel 9LVLyQ*HQHUDO Un modulo del kernel es sencillamente un fichero objeto que contiene las rutinas y/o datos a cargar en el kernel que se está ejecutando. Cuando se carga, el código del modulo reside en el espacio de memoria del kernel y se ejecuta íntegramente en su contexto. Técnicamente, un modulo puede ser considerado como un conjunto de rutinas cualesquiera, con la única excepción de que existen dos rutinas de nombre obligado: LQLWBPRGXOH y FOHDQXSBPRGXOH Obviamente, estas son ejecutadas al cargar y descargar el modulo del kernel respectivamente, y por lo demás, el programador que realice un modulo debe tener en cuenta todas las restricciones asociadas a la generación de manejadores. El cargar un modulo en el kernel supone 4 tareas principales: 1.- Preparar el modulo para el espacio de la memoria. Leer el fichero objeto del disco y resolver todos los símbolos externos. Un modulo sólo puede acceder a aquellos módulos ya existentes en el kernel. Este paso lo realiza una parte del kernel llamada ‘UXQWLPH module ORDGHU’. 2.- Reservar memoria en el espacio de memoria del kernel para el nuevo módulo, tanto para código como para datos, así como para información adicional del módulo. 3.- Copiar el código del módulo en su nueva dirección y proveer al kernel de toda aquella información relevante para mantener el module (como la nueva tabla de símbolos). 4.- Ejecutar LQLWBPRGXOH ya formando parte del kernel, del modulo en cuestión. (OFDUJDGRUGHPyGXORV El cargador de módulos de /LQX[, LQVPRG es responsable de leer un objeto, obtener su lista de símbolos, resolver todas las referencias del modulo, y enviar ese modulo al kernel para su ejecución. El código fuente relativo al mismo, así como del kernel de /LQX[ por completo,. está disponible en Internet. El formato en sistemas de /LQX[ es el típico de ficheros ‘a.out’, aunque más recientemente se están implementando ZZZGDWVLILXSPHV 3DJ Jorge OCÓN ALONSO Tutor: Juan Zamorano <[email protected]> soporte para ficheros de tipo ELF, y las ultimas versiones de los módulos las soportan. Los ficheros de tipo a.out se almacenan como una cabecera, seguida de segmentos de código y de datos, información relativa a la carga dinámica, la tabla de símbolos, y la tabla de cadenas de caracteres. Todas estas partes son leídas por insmod para su uso posterior: La tabla de símbolos se almacena en el fichero objeto como un array de estructuras de tipo VWUXFWQOLVW. Los nombres de los símbolos se encuentran en la tabla de cadenas, inmediatamente después de la tabla de símbolos del fichero. Cada entrada a la tabla de símbolos contiene el desplazamiento del nombre asociado dentro de la estructura (tipo n_un.n_strx). 2.- Se lee la tabla de símbolos. Dentro de LQVPRG, cada símbolo es leído e insertado en un árbol binario para que la búsqueda de símbolos sea más eficiente. Las direcciones de los símbolos BLQLWBPRGXOH y BFOHDQXSBPRGXOH, la funciones de inicialización y de borrado se salvan para su uso posterior. 3.- Resolución de todas las referencias externas. LQVPRG obtiene la lista de símbolos del kernel utilizando la llamada JHWBNHUQHOBV\PV, la cual devuelve un array de estructuras de tipo VWUXFWNHUQHOBV\P, cada una de cuyas entradas contiene el nombre y la dirección en el kernel de un símbolo. Una vez que se han resuelto los símbolos, LQVPRG busca en el árbol generado a partir de la tabla de referencias externas, actualizando el campo QBYDOXH de cada estructura de tipo QOLVW con el valor de la dirección de dicha variable, que es ya una dirección del kernel. Si no se obtiene la dirección de todas las variables externas referenciadas, se emite un mensaje de error, y se sale sin insertar el módulo. 4.- Se reajustan las direcciones del kernel actualizando las direcciones reales en el kernel de las variables referenciadas, tanto en la zona de código como en la de datos. Se utiliza una estructura de tipo UHORFDWLRQBLQIR. Una vez hecho esto, todas las referencias externas del módulo apuntan a las direcciones del kernel apropiadas. 5.- Se reserva espacio de memoria para el módulo mediante una llamada a FUHDWHBPRGXOH Como argumentos para FUHDWHBPRGXOH tenemos el nombre del modulo y su tamaño total. 6.- Se carga el modulo en la memoria del kernel mediante una llamada a LQLWBPRGXOH . Esta llamada tiene varios argumentos, y LQVPRG debe de construir las estructuras de datos antes de hacer la llamada. Parámetros para esta llamada son el nombre del modulo, los nombres de los segmentos de texto y de datos, el tamaño del código en bytes, y punteros a estructuras en las cuales hay punteros a las funciones init_module y FOHDQXSBPRGXOH, así como una estructura que indica cual son los símbolos del módulo y sus variables y cuales son externos. Según se resuelven las referencias a los símbolos del kernel, se actualizan las tablas del kernel para que contengan los símbolos del nuevo módulo. 3DJ ZZZGDWVLILXSPHV Manejador de tipo Módulo para la SCC-8530 en LINUX Trabajo de doctorado Obsérvese que no hay que confundir la llamada a LQLWBPRGXOH (escrita por el programador del manejador) con la llamada del sistema LQLWBPRGXOH, que forma parte del kernel del sistema, y sirve para insertar un módulo cualquiera. ,16(5&,Ï1'(6,167$/$&,21'(/.(51(/ Como ya hemos comentado anteriormente, el manejador se carga dinámicamente, lo que quiere decir que no forma parte del sistema operativo inicialmente, sino que, una vez arranca el sistema operativo, mediante una serie de instrucciones se realiza la carga del manejador. Esto permite mucha mayor flexibilidad a la hora de desarrollarlo pues no es necesario compilarlo junto con el resto del sistema operativo cada vez que se genera una nueva versión. Como ya dijimos anteriormente, /LQX[ dispone de la instrucción LQVPRG para cargar un módulo dinámicamente en el sistema operativo. Se facilita enormemente la tarea al programador, que sencillamente tiene que compilar con unos SUDJPDV determinados. Después de realizar las tareas anteriormente descritas, insmod llama automáticamente a una rutina dentro del código del manejador que se encarga de realizar la inicialización del manejador (LQLWBPRGXOH). ¿Que es lo que se ha de hacer durante la inicialización del módulo?. Básicamente, reservar memoria para las estructuras de datos, detectar la presencia o no de los chips de comunicaciones para evitar fallos en caso de que no estén en el sistema, ajustar los vectores de interrupción de todas las 86$57s asociadas, e inicializar las estructuras de datos del manejador. Esto es lo que se hace en la rutina de nombre LQLWBPRGXOH (el nombre esta forzado por el sistema de modo que todo manejador que se cargue dinámicamente debe de tener una rutina con ese nombre). La rutina init_module solo utiliza unas pocas variables locales para inicialización. La primera parte es la siguiente: LQWLQLWBPRGXOHYRLG ^ LQWFKLSFKDQASDUDLQGH[DUQXPHURGHFKLS\GHFDQDO UHJLVWHULRBSRUWFWUO3DUDDFFHGHUDORVSXHUWRVGHFRQWUROGHODV86$57 ORQJIODJVGHOD&38 /* Se inicializan algunas estructuras de datos necesarias para el manejador.: */ PHPVHWVFFBGULYHUVL]HRIVWUXFWWW\BGULYHU VFFBGULYHUPDJLF 77<B'5,9(5B0$*,&PDJLFRGHOVLVWHPD VFFBGULYHUQDPH VFF VFFBGULYHUPDMRU =B0$-259HUVLyQ VFFBGULYHUPLQRUBVWDUW 'LVSRVLWLYRPHQRU VFFBGULYHUQXP 1FKLSV1XPHURGHFDQDOHV VFFBGULYHUW\SH 77<B'5,9(5B7<3(B6(5,$/7LSRGHGHYLFH VFFBGULYHUVXEW\SH 1RHVQHFHVDULR VFFBGULYHULQLWBWHUPLRV WW\BVWGBWHUPLRV VFFBGULYHULQLWBWHUPLRVFBFIODJ % _&6_&5($'_+83&/_&/2&$/ ZZZGDWVLILXSPHV 3DJ Jorge OCÓN ALONSO Tutor: Juan Zamorano <[email protected]> VFFBGULYHUIODJV 77<B'5,9(5B5($/B5$: VFFBGULYHUUHIFRXQW VFFBUHIFRXQW VFFBGULYHUWDEOH VFFBWDEOH VFFBGULYHUWHUPLRV VWUXFWWHUPLRVVFFBWHUPLRV VFFBGULYHUWHUPLRVBORFNHG VWUXFWWHUPLRVVFFBWHUPLRVBORFNHG Seguidamente, se ajustan los punteros a funciones del manejador, que serán los puntos de entrada para las distintas llamadas propias de un manejador de tipo carácter: VFFBGULYHURSHQ VFFBRSHQ VFFBGULYHUFORVH VFFBFORVH VFFBGULYHUZULWH VFFBZULWH VFFBGULYHUVWDUW VFFBVWDUW VFFBGULYHUVWRS VFFBVWRS VFFBGULYHUSXWBFKDU VFFBSXWBFKDU; VFFBGULYHUIOXVKBFKDUV VFFBIOXVKBFKDUV VFFBGULYHUZULWHBURRP VFFBZULWHBURRP VFFBGULYHUFKDUVBLQBEXIIHU VFFBFKDUVBLQBEXIIHU VFFBGULYHUIOXVKBEXIIHU VFFBIOXVKBEXIIHU VFFBGULYHUWKURWWOH VFFBWKURWWOH VFFBGULYHUXQWKURWWOH VFFBXQWKURWWOH VFFBGULYHULRFWO VFFBLRFWO VFFBGULYHUVHWBWHUPLRV VFFBVHWBWHUPLRV Se registra el manejador como de tipo terminal en el kernel : LIWW\BUHJLVWHUBGULYHUVFFBGULYHU SDQLF&RXOGQ WUHJLVWHU=6&&GULYHU?Q La rutina printk es el equivalente a printf para los manejadores. Funciona de modo diferente, pues es mas rápida para evitar bloqueos y además la salida por defecto se produce en el fichero de log del sistema (/vad/adm/messages). Pese a todo ello, debe de usarse con cautela en interrupciones críticas, pues consume bastante tiempo. SULQWN%$11(5 SULQWN%$11(5 SULQWN%$11(5 Esta sentencia evita el que se pueda acceder a zonas de memoria no válidas en caso de que Nchips tenga una valor superior al del máximo numero de chips contemplados. LI1FKLSV!0$;6&&1FKLSV 0$;6&& 3DJ ZZZGDWVLILXSPHV Manejador de tipo Módulo para la SCC-8530 en LINUX Trabajo de doctorado El código que viene a continuación realiza la inicialización de las estructuras de datos de las UART, y además comprueba que los chips están instalados, es decir, realiza la autodetección de los dispositivos. La rutina FKHFNBUHJLRQ solicita al sistema operativo el acceso al puerto cuya dirección es la que se le indica como argumento. Una vez detectada la existencia del chip, mediante UHTXHVWBUHJLRQ se solicita esas direcciones de I/O como direcciones propias de este manejador. Finalmente, se informa al usuario de los resultados de la búsqueda, así como de los canales disponibles. Cada 86$57 dispone de dos canales, de modo que por cada chip detectado el usuario dispondrá de dos canales, a los que accederá como ficheros del directorio /dev. Las direcciones base e IRQs utilizadas por cada chip están predeterminadas ( Base 01b0 e IRQ 5 para el primer chip y base 01b4 y e IRQ 7 para el segundo). De este modo, al terminar la inicialización el usuario dispone de los siguientes canales: /dev/scc0 como canal A del primer chip. /dev/scc1 como canal B del primer chip. /dev/scc2 como canal A del segundo chip. /dev/scc3 como canal B del segundo chip. Y de ahí en adelante... El vector de interrupción no se ha activado aun por motivos de seguridad del sistema, eso se hará mas adelante, cuando mediante una llamada especifica se inicialize el manejador. ,QLFLDOL]DWRGRVORVFKLSVGHOVLVWHPD IRUFKLS FKLS1FKLSVFKLS ^ PHPVHWFKDU6&&B,QIR>FKLS@VL]HRIVWUXFWVFFBFKDQQHO PHPVHWFKDU6&&B,QIR>FKLS@VL]HRIVWUXFWVFFBFKDQQHO FWUO 6&&BFWUO>FKLS@ LIFWUO FRQWLQXH 'DGRTXHODVRSHUDFLRQHVGH(6FRQHOSXHUWRVHKDFHQHQGRVIDVHVKD\TXH LQKLELULQWHUUXSFLRQHV VDYHBIODJVIODJVFOL FKHFNBUHJLRQFWUO 2XWEFWUO 2XW5HJFWUO5[ &RPSUREDFLyQGHTXHHOFKLSHVWiHQHOVLVWHPD LI,Q5HJFWUO5 [ ^ UHVWRUHBIODJVIODJV FRQWLQXH ` 6&&B,QIR>FKLS@PDJLF 6&&B0$*,& 6&&B,QIR>FKLS@FWUO 6&&BFWUO>FKLS@ ZZZGDWVLILXSPHV 3DJ Jorge OCÓN ALONSO Tutor: Juan Zamorano <[email protected]> 6&&B,QIR>FKLS@GDWD 6&&BGDWD>FKLS@ 6&&B,QIR>FKLS@HQKDQFHG 6&&B(QKDQFHG>FKLS@ 6&&B,QIR>FKLS@QXPEHU FKLS 6&&B,QIR>FKLS@PDJLF 6&&B0$*,& 6&&B,QIR>FKLS@FWUO 6&&BFWUO>FKLS@ 6&&B,QIR>FKLS@GDWD 6&&BGDWD>FKLS@ 6&&B,QIR>FKLS@HQKDQFHG 6&&B(QKDQFHG>FKLS@ 6&&B,QIR>FKLS@QXPEHU FKLS UHVWRUHBIODJVIODJV ` SULQWN,QLW=GULYHUXFKDQQHOVXVLQJXLUTV?Q1FKLSV,YHF1 IRUFKDQ FKDQ1FKLSVFKDQ ^ SULQWNGHYVLGDWDSRUW [[FRQWUROSRUW [[V?Q VFFBGULYHUQDPHFKDQ6&&BGDWD>FKDQ@6&&BFWUO>FKDQ@ 6&&B,QIR>FKDQ@FWUO"IRXQGPLVVLQJ LI6&&B,QIR>FKDQ@FWUO ^ 6&&BFWUO>FKDQ@ `HOVH^ UHTXHVWBUHJLRQ6&&BFWUO>FKDQ@VFFFWUO UHTXHVWBUHJLRQ6&&BGDWD>FKDQ@VFFGDWD ` ` UHWXUQ ` Este es el código que se ejecuta cada vez que se realiza una inserción del modulo, si bien no es suficiente para que se active el manejador. Para realizar esto, será preciso una llamada adicional del programa usuario (una llamada LRFWO con parámetro SCC_INIT) que activa la rutina siguiente: VWDWLFYRLG ]BLQLWYRLG ^ VWUXFWVFFBFKDQQHO VWUXFWVFFBFKDQQHO LQW XQVLJQHGORQJ LQW LQW LQW 3DJ VFF3XQWHURDFDQDO$GHOD6&& VFFE,GHPFDQDO% FKLSGHFKLSTXHHVWDPRVHGLWDQGR IODJVGHOD&38 UHVXOW5HVXOWDGRGHODXOWLPDRSHUDFLRQ VFFLUT,QWHUUXSFLyQGHOD6&&SHGLGD L ZZZGDWVLILXSPHV Manejador de tipo Módulo para la SCC-8530 en LINUX Trabajo de doctorado En primer lugar, la rutina fuerza un RESET de todos los chips presentes en el sistema. Esto en la 86$57 se realiza escribiendo en el registro 9 del canal A un valor predeterminado (FHWRES). Se utilizan punteros a funciones para cada tipo de interrupción (TXBE,EXST,RXXS,SPRX), que inicialmente apuntan a una función nula. Posteriormente, cuando el usuario defina el protocolo a soportar por ese canal, se cambiaran dichos punteros a las funciones C apropiadas según el protocolo. Esto le da mayor flexibilidad al manejador, permitiendo soportar distintos protocolos con el mismo código. El salvar los IODJV e inhibir las interrupciones se debe a que las operaciones de lectura y escritura son binarias, como ya se ha comentado. En el registro 2 se escribe un vector que posteriormente nos indicara de a que canal y a cual chip ha llegado una interrupción. IRUFKLS FKLS1FKLSVFKLS ^ VFF 6&&B,QIR>FKLS@ VFF!IXQF>@IQ VFF!IXQF>@IQ VFF!IXQF>@IQ VFF!IXQF>@IQ QRLQW VFFE VFF VFFE!IXQF>@IQ VFFE!IXQF>@IQ VFFE!IXQF>@IQ VFFE!IXQF>@IQ QRLQW LIVFF!FWUO FRQWLQXH VDYHBIODJVIODJVFOL ,QLFLDOL]DFLyQGHOFKLSSURSLDPHQWHGLFKR 2XWEVFF!FWUO 2XW5HJVFF!FWUO5)+:5(6 )XHU]DHOUHVHW+DUGZDUH XGHOD\/ 'DOHXQSRFRGHWLHPSRPDVGHOUHTXHULGR ZUVFF5FKLS 9HFWRUGH,QWHUUXSFLyQ ZUVFF59,6 (OYHFWRULQFOX\HHVWDGR UHVWRUHBIODJVIODJV ` +DELOLWDGHQXHYRODVLQWHUUXSFLRQHV IRUL L,YHF1L ^ VFFLUT ,YHF>L@ LIVFFLUT VFFLUT 3DUWLFXODULGDGHVGHOGLVHxRGHO3&GHVGHHO,%0$7 UHVXOW UHTXHVWBLUTVFFLUTVFFBLVU6$B,17(55837'5,9(56&& ` 6&&ORJ5HVXOWDGRGHUHTXHVWBLUT GUHVXOW 'ULYHUB,QLWLDOL]HG ` ZZZGDWVLILXSPHV 3DJ Jorge OCÓN ALONSO Tutor: Juan Zamorano <[email protected]> La rutina UHTXHVWBLUTdel kernel nos permite solicitar un vector de interrupción para su uso por el manejador. En la arquitectura del IBM PC, las interrupciones 3 y 4 se utilizan en /LQX[ para las líneas de comunicaciones serie (el equivalente al COM1 y COM2 del MS-DOS), por lo que utilizarlas sería eliminar la posibilidad de usar por ejemplo el ratón y otras capacidades de comunicaciones. La IRQ 2 está multiplexada en cascada de modo que no interesa utilizarla. La IRQ 6 se utiliza para la disquetera. La IRQ 5 en principio queda libre, así como la IRQ 7 que es utilizada por el manejador de impresora, pero dicho manejador puede funcionar en modo poll, en el que no es preciso trabajar mediante interrupciones. Por tanto, utilizo las IRQ 5 y 7 permitiendo el uso de 2 USART, o, lo que es lo mismo, 4 canales de comunicaciones. Una vez instalado el manejador con LQVPRG, y realizada la llamada LRFWO con SCC_INIT, el manejador está inicializado y listo para su utilización posterior. El proceso de instalación del manejador en el kernel queda completado. Realizar el paso inverso, esto es desinstalarlo del kernel, puede ser realizado mediante la ejecución de UPPRG que es el descargador de módulos. Esto, aparte de facilitar enormemente el desarrollo (se puede instalar y desinstalar una versión en cuestión de segundos), permite reajustar el kernel según nuestras necesidades y es naturalmente mucho más elegante. Veamos en detalle la función que elimina el modulo del kernel: YRLGFOHDQXSBPRGXOHYRLG ^ ORQJIODJV LQWVFFLUT XQVLJQHGFKDQ LQWL Lo primero que hace la función correspondiente es determinar si el modulo está actualmente en uso o no por algún proceso. Si es así será imposible descargarlo de la memoria, debiendo esperar a que el proceso dueño canal haga una llamada a FORVH (el sistema lo haría automáticamente caso de que el proceso muriese). En caso contrario, se elimina de la lista de WW\V el GHYLFH de tipo SCC, se liberan (mediante UHOHDVHBUHJLRQ y IUHHBLUT) las direcciones base e IRQs de los chips correspondientes, y se desactivan los temporizadores asociados al manejador de la SCC. Estos temporizadores son comunes a todo el kernel, y se utilizan para obtener una base de tiempos de una precisión de en torno a los 30 milisegundos, sin que ello conlleve una sobrecarga del sistema. LI02'B,1B86( SULQWN0RGXORDFWXDOPHQWHHQXVRLPSRVLEOHGHVFDUJDU?Q HOVH ^ LIWW\BXQUHJLVWHUBGULYHUVFFBGULYHU SDQLF&RXOGQ WXQUHJLVWHU=6&&GULYHU?Q SULQWN8QORDGLQJ=GULYHUXFKDQQHOVXVLQJXLUTV?Q1FKLSV,YHF1 VDYHBIODJVIODJVFOL 3DJ ZZZGDWVLILXSPHV Manejador de tipo Módulo para la SCC-8530 en LINUX Trabajo de doctorado IRUFKDQ FKDQ1FKLSVFKDQ ^ SULQWNGHYVLGDWDSRUW [[FRQWUROSRUW [[V?Q VFFBGULYHUQDPHFKDQ6&&BGDWD>FKDQ@6&&BFWUO>FKDQ@ 6&&B,QIR>FKDQ@FWUO"IRXQGPLVVLQJ LI6&&B,QIR>FKDQ@FWUO ^ UHOHDVHBUHJLRQ6&&BFWUO>FKDQ@ UHOHDVHBUHJLRQ6&&BGDWD>FKDQ@ ` ` LI'ULYHUB,QLWLDOL]HG ^ IRUL L,YHF1L ^ VFFLUT ,YHF>L@ LIVFFLUT VFFLUT 3RUHOGLVHxRGHO,%0B3& IUHHBLUTVFFLUT ` WLPHUBWDEOH>6&&B7,0(5@IQ WLPHUBWDEOH>6&&B7,0(5@H[SLUHV WLPHUBDFWLYH a6&&B7,0(5 ` UHVWRUHBIODJVIODJV ` ZZZGDWVLILXSPHV 3DJ Jorge OCÓN ALONSO Tutor: Juan Zamorano <[email protected]> 86$1'2(/0$1(-$'25 Hemos visto como se instala en el kernel el manejador. Pero no debemos perder de vista que el manejador no es sino un servidor diseñado para que otros programas lo utilicen y realicen comunicaciones serie pudiendo desentenderse del manejo del dispositivo ( en este caso, de las USART de comunicaciones). Para ello, el programa que utilice el manejador deberá seguir un determinado protocolo. Dicho protocolo se traduce en una serie de llamadas estándar de 81,; (RSHQFORVHZULWHUHDGLRFWO) que el propio sistema operativo se encargará de progresar hacia el manejador. Es durante el proceso de carga del modulo cuando el manejador indica al sistema operativo cual es la correspondencia entre las llamadas 81,; y sus rutinas para tratar dichas llamadas, lo que llamábamos SXQWRVGHHQWUDGD . Anteriormente comentábamos que la visión desde el punto de vista de un proceso del manejador, siguiendo la filosofía del 81,;, era la de un fichero. Que se adoptaba el nombre /dev/sccX, con X=0,1,2,3 según el canal que se estuviese utilizando, para que el usuario indicase el canal por el que comunicar. Quiere esto decir que para empezar a trabajar con un canal, el programa usuario que utilice el manejador debe de realizar una llamada RSHQ de 81,; con el nombre de uno de estos ficheros según el canal que desee utilizar. Así, si se desea usar el canal A de la primera SCC, el programa usuario realizaría una llamada RSHQ³GHYVFF´ PRGR Esta llamada devuelve un identificador de canal, que es el que se utiliza en subsiguientes llamadas al dispositivo (ZULWHUHDGLRFWO). Finalmente, una llamada a FORVH indicaría al sistema que no se desea trabajar mas con él. Veamos la rutina VFFBRSHQ, que se activa al realizar la llamada RSHQcon el nombre del fichero de un canal. Para aclarar un poco las cosas, diremos que esta es la zona de código que se activa en el manejador cuando el programa usuario (cualquier proceso que utiliza esta linea) hace una llamada a open con /dev/sccx como argumento.: LQWVFFBRSHQVWUXFWWW\BVWUXFWWW\VWUXFWILOHILOS ^ VWUXFWVFFBFKDQQHOVFF LQWFKDQ LQWIODJV Lo primero que hace la rutina es comprobar que los parámetros que se le pasan son correctos. Esto es muy crítico pues como decíamos anteriormente, una caída del manejador normalmente implica una caída general del sistema. En caso de error de algun parámetro, se devuelve el tipo de error y se termina la llamada LIWW\ UHWXUQ(12'(9 FKDQ 0,125WW\!GHYLFHWW\!GULYHUPLQRUBVWDUW 3DJ ZZZGDWVLILXSPHV Manejador de tipo Módulo para la SCC-8530 en LINUX Trabajo de doctorado LIFKDQ__FKDQ! 1FKLSV UHWXUQ(12'(9 VFF 6&&B,QIR>FKDQ@ WW\!GULYHUBGDWD VFF WW\!WHUPLRV!FBFIODJ a&%$8' La llamada realiza en primer lugar una serie de comprobaciones de los argumentos recibidos para que no se produzcan más adelante errores fatales (recordemos que si se produjese un error de accesos a memoria, etc... dentro del código del manejador se produciría una caída general de todo el sistema). Para el canal pedido, se comprueba que está disponible (esto significa que el algoritmo de detección en el arranque identificó que el sistema disponía del chip asociado a dicho canal), se incrementa el contador que indica que está siendo usado, y se devuelve que no hay error en el caso de que todo sea correcto. LIVFF!WW\ 18// ^ VFF!WW\BRSHQHG SULQWNVFFBRSHQ'ULYHUEXV\ UHWXUQ(%86< ` LIGHI02'8/( RSHQV SULQWNVFFBRSHQRSHQV GRSHQV 02'B,1&B86(B&2817 HQGLI LI'ULYHUB,QLWLDOL]HG ^ SULQWNVFFBRSHQ'ULYHUQRWLQLWLDOL]HG UHWXUQ ` LIVFF!PDJLF 6&&B0$*,& ^ SULQWN(5525VFFBRSHQEDGPDJLFQXPEHUIRUGHYLFHGG0$-25WW\ !GHYLFH0,125WW\!GHYLFH UHWXUQ(12'(9 ` VFF!WW\ WW\ UHVHWBP\ORJVFF VFF!IUDPHBVL]H %8)6,=( VDYHBIODJVIODJVFOL ZZZGDWVLILXSPHV 3DJ Jorge OCÓN ALONSO Tutor: Juan Zamorano <[email protected]> WLPHUBWDEOH>6&&B7,0(5@IQ VFFBWLPHU WLPHUBWDEOH>6&&B7,0(5@H[SLUHV QRZ WLPHUBDFWLYH_ 6&&B7,0(5 UHVWRUHBIODJVIODJV UHWXUQ ` Las tablas de temporizadores pertenecen al kernel del sistema, concretamente a la parte del kernel encargada de manejo de los terminales. El manejador utiliza estas tablas para generar temporizadores de múltiplos de 30 ms de una forma elegante, sin interceptar la interrupción de reloj, y evitando una sobrecarga del sistema. A partir de este punto el usuario debe de programar la línea con alguno de los protocolos disponibles: Esto se realiza mediante una llamada VFFBLRFWO con los parámetros correspondientes a 6&&B63527 En el código original, el protocolo se fijaba elemento por elemento, hasta quedar definitivamente configurado. Era mejor para el tipo de aplicaciones que se iban a fijar por nosotros el utilizar unas tablas de inicialización de registros, que definiesen de forma fija los diferentes parámetros a utilizar, y dejar abierta la posibilidad de modificar unos pocos parámetros (como la velocidad), dinámicamente, una vez programada la línea. La llamada LRFWO se utiliza también para poder enviar o recibir tramas del sistema. ¿Por qué utilizar esta llamada en lugar de las tradicionalesUHDG o ZULWH para lectura ó escritura?. La razón es un tanto singular. Siendo un manejador de PRGRFDUiFWHU el modo en que se procesan las lecturas y escrituras es carácter a carácter, no por tramas completas. Esto, que es muy frecuente en síncrono, no lo es tanto en asíncrono, donde la estructura de la trama está definida por la llegada de los IODJV de inicio y de fin, y el propio hardware dispone de elementos que se encargan de la detección automática de principio/fin de trama, inserción automática de ceros, y cálculo del CRC. En las comunicaciones síncronas las llamadas a UHDG o ZULWH van asociadas a mensajes completos ó tramas. No ocurre así en las comunicaciones asíncronas, en donde generalmente se reciben y envían los datos carácter a carácter, y se determina por software el principio y el fin de trama, así como el cálculo del CRC. Por ser un manejador de modo carácter, las llamadas a ZULWH del proceso usuario QRVHFRUUHVSRQGHQFRQXQD~QLFDOODPDGDDZULWHHQHOFyGLJRGHOPDQHMDGRU., esto es, puede ocurrir que una llamada a write del proceso usuario en la que se solicite el envío de 200 bytes se corresponda con varias llamadas a la rutina scc_write dentro del código del manejador (por ejemplo llamadas sucesivas con 20,30,100 y 50 bytes, totalizando los 200 solicitados por el proceso usuario). Para evitar esto, sería necesario cambiar el manejador a un manejador de tipo bloque, lo cual no resultaba interesante por otros motivos que se expondrán mas adelante. Problema: ¿ como determinar donde empieza y donde acaba una trama que el proceso usuario ha solicitado enviar ?. En el manejador original, se determinaba el principio/fin de trama mediante un protocolo (NLVVHQFRGHUGHFRGHU) acordado entre proceso usuario y manejador. De esta 3DJ ZZZGDWVLILXSPHV Manejador de tipo Módulo para la SCC-8530 en LINUX Trabajo de doctorado forma, al recibir una llamada a ZULWH, el manejador examinaba el contenido de los datos que se quería enviar para determinar si era parte de una trama o bien una trama completa. Si no constituía una trama, se almacenaba en memoria pero no se comenzaba a transmitir físicamente. Igualmente, en recepción, al terminar de recibir una trama, se codificaba en protocolo NLVV y se almacenaba en una zona de memoria. El proceso usuario, realizando sucesivas llamadas a UHDG, decodificaba igualmente la trama recibida en protocolo NLVV, y de este modo determinaba los principios y finales de tramas. Este método me pareció francamente ineficiente puesto que forzaba la existencia de codificadores/decodificadores en ambas partes (manejador y proceso usuario) para solventar un problema de concepto. Podría haber optado por desarrollar un manejador de tipo bloque, pero ello hubiese impedido su utilización como manejador de carácter en determinados protocolos asíncronos. En 81,; existe una llamada,LRFWO, que se usa en general para fijar parámetros del dispositivo que se está usando. Esta llamada es de propósito general, por lo que admite varios argumentos, siendo un de ellos el tipo de llamada ioctl a realizar. Así pues, decidí implementar llamadas especiales a LRFWOque son6&&B5($'y 6&&B:5,7(, de modo que estas llamadas se utilizasen especialmente para realizar HO HQYtR \ OD OHFWXUD GH WUDPDV VLQFURQDV FRPSOHWDV Cada llamada a ioctl con argumento 6&&B5($' y/o 6&&B:5,7( entregaba ó transmitía una trama, con lo que era innecesario codificar/decodificar las tramas en protocolo NLVV. Las llamadas a UHDG y ZULWH quedaban como llamadas para protocolos asíncronos, preservando así la posibilidad de transferir en asíncrono byte a byte. De este modo, tenemos simultáneamente capacidades de recepción y transmisión en modo bloque y/o en modo carácter, lo cual es sumamente interesante dado el amplio espectro de protocolos con los que necesitamos trabajar. En el modo normal de funcionamiento en síncrono, pues, se utilizan sucesivas llamadas a LRFWO( 6&&B:5,7( para transferir tramas y llamadas a LRFWO 6&&B5($'para recibir tramas. Cada llamada a ioctl se traduce en la recepción /el envío de una trama completa (según sea6&&B5($' ó 6&&B:5,7(). La llamada ioctl en este manejador tiene, además de estas dos funciones, las siguientes: 6&&B63((': 6&&B,1,7: 6&&B567$7 6&&B:5,7( 6&&B5($' 6&&B/2* 6&&B06,=( transferir por la línea Cambio de la velocidad de la línea. Inicialización general del manejador, Obtención de estadísticas de un canal. Envío de una trama Recepción de una trama Activación/desactivación del buffer de log. Determina el tamaño máximo de trama que se puede En lo sucesivo, veremos en detalle como funciona la llamada LRFWO, que es la utilizada por el programa cliente para utilizar el manejador en síncrono (ignorando las llamadas a ZULWH y UHDG por los motivos anteriormente expuestos). ZZZGDWVLILXSPHV 3DJ Jorge OCÓN ALONSO Tutor: Juan Zamorano <[email protected]> $1$/,6,6'(/&2',*25(/$7,92$/$ //$0$'$,2&7/ VWDWLFLQW VFFBLRFWOVWUXFWWW\BVWUXFWWW\VWUXFWILOHILOHXQVLJQHGLQWFPGXQVLJQHGORQJDUJ ^ VWUXFWVFFBFKDQQHOVFF WW\!GULYHUBGDWD XQVLJQHGORQJU XQVLJQHGLQWUHVXOW XQVLJQHGLQWHUURU XQVLJQHGLQWL XQVLJQHGUHWU\V La rutina se protege de fallos tales corrupción de la memoria mediante la comprobación de que hay determinados valores en determinadas posiciones de memoria. Esto evita problemas de caída del sistema: LIVFF!PDJLF 6&&B0$*,& ^ SULQWN(5525VFFBLRFWOEDGPDJLFQXPEHUIRUGHYLFHGG 0$-25WW\!GHYLFH0,125WW\!GHYLFH UHWXUQ(12'(9 ` U 12B68&+B3$5$0 Una primera función de LRFWO es la de inicialización del manejador. Si no se ha realizado aún, cualquier otra llamada a LRFWO no tiene sentido: LI'ULYHUB,QLWLDOL]HG ^ LIFPG 7,2&6&&,1, ^ LIVXVHU UHWXUQ(3(50 ]BLQLW UHWXUQ ` UHWXUQ(,19$/ ` 3DJ $UJXPHQWRQRYDOLGRSRUQRHVWDULQLFLDOL]DGRHOVLVWHPD ZZZGDWVLILXSPHV Manejador de tipo Módulo para la SCC-8530 en LINUX Trabajo de doctorado A continuación se tratan los comandos normales, LOGFLIP y RDLOG se usan como mecanismo de depuración VZLWFKFPG ^ FDVH6&&B/2*)/,3 VFF!ORJEXIORJJLQJ VFF!ORJEXIORJJLQJ" EUHDN FDVH6&&B5'/2*/HHHQEXIIHUGH/2* ^ HUURU YHULI\BDUHD9(5,)<B:5,7(YRLGDUJVL]HRI%8))(5B/2* LIHUURU UHWXUQHUURU 6&&ORJ&RSLRE\WHVGH/2*HQEXIIHU%XISRV G VFF!ORJEXIEXISRV PHPFS\BWRIVYRLGDUJVFF!ORJEXIVL]HRI%8))(5B/2* UHWXUQ EUHDN ` SCC_WRITE es la función que realiza el envío de tramas por la línea. Existe un puntero a función dentro del canal que le indica la función específica para cada protocolo: FDVH6&&B:5,7((VFULELUWUDPD ^ HUURU YHULI\BDUHD9(5,)<B5($'YRLGDUJVL]HRI)5$0( LIHUURU UHWXUQHUURU PHPFS\BIURPIVRXUBIUDPHYRLGDUJVL]HRI)5$0( /ODPDPRVDODIXQFLRQTXHHVFULEH LIRXUBIUDPHFRQWURO UHWU\V RXUBIUDPHFRQWURO HOVH UHWU\V LIVFF!ZULWHIFQ ^ UHVXOW VFF!ZULWHIFQVFFRXUBIUDPHUHWU\V ` HOVH ^ ZZZGDWVLILXSPHV 3DJ Jorge OCÓN ALONSO Tutor: Juan Zamorano <[email protected]> UHVXOW ()$8/7 ` UHWXUQUHVXOW EUHDN ` 6&&B63(('HVODOODPDGDSDUDHOFDPELRGHYHORFLGDGGHWUDQVPLVLyQUHFHSFLyQ FDVH6&&B63((' ^ IRUL L0$;B63(('L ^ LIVSBGHIHFWR>L@ DUJ ^ VFF!PRGHPVSHHG DUJ VHWBVSHHGVFF UHWXUQ ` ` UHWXUQ(,19$/ EUHDN ` /* MSIZE fija el tamaño máximo de mensaje a recibir/enviar. */ FDVH6&&B06,=( ^ LIDUJ!%8)6,=(__DUJ UHWXUQ(,19$/ HOVH VFF!IUDPHBVL]H DUJ UHWXUQ EUHDN ` /* SCC_READ es la función de lectura de trama. Es también dependiente del protocolo. */ FDVH6&&B5($'/HFWXUDGHWUDPD ^ 6&&ORJ/HFWXUDGHWUDPD /ODPDPRVDODIXQFLRQGHOHFWXUD LIVFF!UHDGIFQ ^ UHVXOW VFF!UHDGIFQVFFRXUBIUDPH ` HOVH 3DJ ZZZGDWVLILXSPHV Manejador de tipo Módulo para la SCC-8530 en LINUX Trabajo de doctorado ^ UHWXUQ()$8/7 ` PHPFS\BWRIVYRLGDUJRXUBIUDPHVL]HRI)5$0( UHWXUQUHVXOW EUHDN ` SCC_START realiza la inicialización del canal, enviando los comandos de inicialización a la USART. Estos comandos son diferentes según el protocolo que hayamos fijado para dicho canal. case SCC_START: /* Inicialización de canal */ { SCClog(1,("inicialización del canal ")); reset_channel(scc); return(0); break; } case SCC_SPROT: /* Inicialización del protocolo */ { if ( ( (int) arg<=MAX_PROTOCOL) && ( (int) arg>0) ) { result = set_protocol( scc, (int) arg ); return(result); } else return( -EINVAL ); break; } case SCC_RSTAT: /* lectura de estadísticas */ { error = verify_area(VERIFY_WRITE, (void *) arg, sizeof(struct scc_stat)); if (error) return(error); SCClog(2,(" Copio bytes de estadisticas en buffer.Bufpos = %d ", scc->logbuf.bufpos)); memcpy_tofs( (void *) arg, &scc->stat, sizeof(struct scc_stat) ); return(0); break; } /* SCC_RINDEX se usa para la lectura de estadísticas generales. */ case SCC_RINDEX: /* lectura de Datos varios del canal */ { ZZZGDWVLILXSPHV 3DJ Jorge OCÓN ALONSO Tutor: Juan Zamorano <[email protected]> error = verify_area(VERIFY_WRITE, (void *) arg, sizeof(INDEX)); if (error) return(error); SCClog(2,(" Copio estado INDEX en buffer")); memcpy_tofs( (void *) arg, &scc->c_trama_env, sizeof(INDEX) ); return(0); break; } SCC_RPROT permite leer el protocolo con el que está funcionando una línea. FDVH6&&B53527OHFWXUDGHHVWDGtVWLFDV ^ LI'ULYHUB,QLWLDOL]HG UHWXUQ()$8/7 HOVH UHWXUQVFF!SURWRFRO EUHDN ` GHIDXOW UHWXUQ(12,2&7/&0' ` UHWXUQ ` CONCLUSIONES El manejador objeto de esta práctica está actualmente funcionando en sistemas de tiempo real (equipos de FRQFHQWUDGRUHV GH HVWDFLyQ) en los trenes de Buenos Aires.(TBA). Los FRQFHQWUDGRUHV GH HVWDFLyQ son equipos de comunicaciones dedicados a la centralización de todos los equipos de estación. Al hablar de HTXLSRVGH HVWDFLyQ nos referimos a lasH[SHQGHGRUDVDXWRPiWLFDVGHELOOHWHV que emiten billetes sin intervención de un operador, las H[SHQGHGRUDV GH YHQWDQLOOD, que emiten billetes con la ayuda de un operador y los PROLQHWHVGHSDVR que controlan el paso de viajeros, comprobando la validez de su billete y anotando en su banda magnética el paso del viajero si fuese necesario. Sin ser un equipo que interaccione con el viajero, la misión de los concentradores es esencial, puesto que ellos son los que recogen los datos de paso de viajeros por los molinetes y de ventas de billetes en las expendedoras de taquilla y automáticas. El concentrador de estación monitoriza y controla todos estos equipos, de forma permanente, almacenando sus averías y alarmas, cambiando su modo de funcionamiento si fuera preciso, ajustando la hora de dichos equipos, etc... 3DJ ZZZGDWVLILXSPHV Manejador de tipo Módulo para la SCC-8530 en LINUX Trabajo de doctorado El FRQFHQWUDGRUGHHVWDFLyQ es un PC Pentium con /LQX[ que trabaja de forma permanente en comunicación constante con los molinetes de paso de viajeros y las máquinas automáticas de venta de billetes, sin asistencia de ningún tipo. Comunica mediante líneas síncronas con dichos equipos (utilizando el manejador objeto de esta práctica), y comunica vía Ethernet y TCP/IP con un equipo principal situado en el Centro de Control de Retiro, desde el cual se puede monitorizar el estado de todas y cada una de las estaciones. En Junio del 97, se habían instalado 3 concentradores en la estación de ONCE, con un total de 12 líneas síncronas. La robustez de /LQX[ queda de manifiesto si examinamos el comportamiento de estos equipos, que sin asistencia de ningún tipo, permanecen durante semanas realizando un gran número de tareas de forma completamente automatizada. A modo de ejemplo, diremos que en uno de los concentradores se habían procesado más de 3 millones de interrupciones de la USART en solo 3 días. Esto sólo nos da una idea del grado de fiabilidad del sistema. En el futuro, se instalarán mas de 97 concentradores de estación en todas las líneas, y se podrán monitorizar desde el Centro de Control de forma remota. El manejador no es sino sólo una pieza más de un conjunto muy extenso de software que abarca desde VFULSWV de configuración del sistema, y programas C de la aplicación, hasta el desarrollo de una distribución de /LQX[ propia que instala a la vez el sistema operativo y nuestras aplicaciones. En este sentido, sólo la condición de /LQX[ de software libre nos ha permitido poder modificar los propios discos de instalación del sistema operativo para que simultáneamente se instalen junto con él nuestras aplicaciones (llegamos a tener que modificar el propio kernel, con todos los mensajes en castellano, modificamos los discos de ERRW y de URRW de instalación, etc... ). Para el usuario del concentrador, la máquina es una caja negra. Una vez instalado el sistema operativo (con nuestra propia distribución), la máquina arranca automáticamente con un usuario creado durante la instalación nuestras aplicaciones. No existen terminales virtuales, ni se pide ORJLQ y SDVVZRUG. El usuario del sistema no sabe UNIX, ni sabe siquiera cual es el sistema operativo de la máquina. Una serie de menús le permiten al operador monitorizar todos los equipos, examinar sus alarmas, enviar ordenes a los equipos remotos para cambiar su modo de funcionamiento, y hacer un mantenimiento del concentrador. Muchas de estas características serían impensables en un sistema operativo comercial, sencillamente porque el fabricante no hubiese suministrado la información precisa para realizarlo. Durante todo el desarrollo, pudimos comprobar diariamente la robustez del sistema, la facilidad de detección de errores y la cantidad de herramientas disponibles para la depuración y como soporte nuestro ( el propio manejador objeto de esta práctica no es sino una ampliación de otro disponible públicamente en Internet ). Todo ello confirma la validez del software libre para sistemas de control de tiempo real, así como la excelente labor realizada por los creadores de /LQX[, a quienes quiero expresar mi más sincero agradecimiento. ZZZGDWVLILXSPHV 3DJ 830'$76, FACULTAD DE INFORMÁTICA 'HSDUWDPHQWRGH$UTXLWHFWXUD\7HFQRORJtDGH6LVWHPDV,QIRUPiWLFRV 8QLYHUVLGDG3ROLWpFQLFDGH0DGULG Campus de Montegancedo Boadilla del Monte 28660 Madrid ESPAÑA Telf: +34 91 336-7399 Fax: +34 91 336-7412 http://www.fi.upm.es ZZZXSPHV