• No results found

Requirements and Specifications Counting Server and Computation Intensive Server

9. Implementation

9.3. Requirements and Specifications Counting Server and Computation Intensive Server

El diseño e implementación de un sistema con Linux embebido puede ser llevado a cabo con una metodología definida, el proceso incluye diferentes tareas, algunas pueden ser realizadas en paralelo algunas pueden incluso ser omitidas en caso de que se emplee alguna distribución de Linux

1. Creando un Sistema Linux de Destino (Target).

Un sistema de este tipo es creado, mediante la configuración y enlazado de los componentes de sistema apropiados; es de resaltar la necesidad en la mayoría de los casos de un sistema anfitrión (host) en el que normalmente se desarrollan las aplicaciones para luego ser cargadas y/o depuradas en el sistema embebido (Target), un host puede tratarse de estaciones de trabajo que funcionen bajo alguna distribución de Linux o cualquier otro sistema operativo como Unix o Windows (Vista, XP, 2000,NT, 98 etc.)

Figura 50: Enlace Host/Target.

Se debe tener en cuenta que independientemente del sistema empleado como Host se deben utilizar herramientas de desarrollo enfocadas al Hardware o Target a emplear y si es el caso que estas herramientas presenten características que permitan la implementación en sistemas Cross-Plataformas, por ejemplo la implementación de un sistema con Linux embebido desde una estación de trabajo que corre bajo Windows. Ver figura 50.

Existen cuatro pasos principales para crear un sistema Linux de Destino:

 Determinar los Componentes del Sistema Requeridos:

Ambiente de

Desarrollo

Cross-Plataforma

HOST

- Bootloader.

- Kernel

-Sistema de

Archivos Raíz

TARGET

Se debe crear una lista con lo elementos realmente necesarios antes de aventurarse a buscar las posibles opciones que puedan presentarse en un momento dado, pues si no se tiene claro lo que se requiere, será muy complicada la selección debido a la gran oferta tanto de Software como de Hardware que hay disponible.

Configurar el Kernel:

Se debe seleccionar una versión del Kernel y una configuración relevante de esta, teniendo en cuenta en lo posible emplear versiones actualizadas y que funcionen de manera estable, evitándose así errores (Bugs) que agregan inestabilidad al sistema y que puedan haber sido arreglados en versiones actualizadas.

Se puede apuntar en términos de estabilidad el hecho de que aun en la actualidad se utiliza la versión 2.4 del Kernel en sistemas embebidos, a pesar de las nuevas versiones disponibles, esto se debe a que los ingenieros que lo usan, encuentran comodidad con su uso y no ven necesidad de utilizar uno mas actual puesto que sus diseños funcionan correctamente. Independientemente de la versión y configuración seleccionada es recomendable mantener la misma configuración del Kernel durante el desarrollo del proyecto para evitar que etapas ya funcionales entren en conflicto al realizar cambios.

Una vez configurado el Kernel es hora de compilarlo (Build) este proceso requiere varios pasos y genera mas de una imagen del Kernel. Puede que algunos de los componentes generados no sean necesarios en otros aspectos del desarrollo del proyecto, pero se recomienda configurar y estructurar todos los componentes del Kernel tan pronto como sea posible para que éstos soporten todos los requerimientos durante el desarrollo y evitar así estar realizando cambios que puedan afectar el funcionamiento del sistema en general.

 Estructurar el Sistema de Archivos Raíz:

El Sistema de Archivos Raíz de un sistema con Linux embebido es similar a la encontrada en una estación de trabajo o servidor corriendo bajo Linux con la excepción de que contienen un set de aplicaciones mínimo, así como las librerías y archivos relacionados justos para correr el sistema adecuadamente.

A este punto se asume una adecuada selección de los componentes requeridos del sistema y no se recomienda retirar ninguno de lo contrario la especificación del Sistema de Archivos Raíz se verá afectada. Es por tanto importante que durante la etapa de determinación de los componentes se

estime de manera lo mas precisa posible el tamaño de cada uno de los componentes el Sistema de Archivos Raíz.

Otra forma de realizar esta labor puede ser mediante pruebas iterativas añadiendo componentes como librerías y herramientas a medida que se desarrolla el proyecto pero es una forma que demanda mas trabajo.

 Configurar el Arranque del Sistema:

Las tareas que quedan pendientes tienen relación con la configuración de los dispositivos de almacenamiento y el Software que gestiona el arranque del sistema (Bootloader), es en esta etapa donde Kernel, Sistema de Archivos Raíz y Bootloader entran a interactuar. Aunque el arranque depende de la arquitectura del sistema, la metodología para empaquetar y arrancar un sistema es similar para diferentes arquitecturas, lo que varía es el tipo de Bootloader y éste depende también de la unidad de almacenamiento desde donde se carga el sistema.

2. Sistema de archivos y módulos

El sistema de archivos es el encargado de realizar la organización y almacenamiento de los archivos en los diferentes dispositivos disponibles en el sistema. En función de las características del dispositivo de almacenamiento y del tipo de información que se va a guardar es preferible utilizar un sistema de archivos u otro. Linux da soporte a varios sistemas de archivos, dentro de los mas utilizados se encuentran ext2, ext3, reiserfs, etc. Estos sistemas de archivos son manejados por una capa denominada Sistema de Archivos Virtual (VFS, del inglés Virtual File System). Esta capa de abstracción provee una visión consistente de los datos almacenados en diferentes dispositivos del sistema. Esta visión es lograda separando el nivel de usuario de los sistemas de archivos, utilizando llamadas estandars al sistema, permitiendo sistemas de archivos lógicos sobre cualquier dispositivo físico. Por lo tanto esta capa abstrae los detalles físicos del dispositivo permitiendo un acceso a los mismos a través de archivos de una manera consistente.

Por debajo de esta capa VFS, el kernel interactúa con dispositivos de E/S a través de controladores de dispositivos (del inglés devices drivers). Estos controladores se encuentran incluidos en el kernel y consisten en estructuras de datos y funciones que controlan uno o más dispositivos como discos rígidos, teclados, mouses, monitores, interfaces de red, dispositivos SCSI. Observamos esta estructura que ha sido descripta por Bovet en el siguiente gráfico.

Uno de los propósitos fundamentales de los controladores de dispositivos es aislar los programas de usuario del acceso a estructuras de datos críticas del kernel y dispositivos de hardware. Además, un controlador de dispositivo oculta al usuario la complejidad y variabilidad de un dispositivo hardware. Por ejemplo, un programa que quiere escribir datos en un disco rígido no tiene en cuenta si el mismo posee sectores de 512 bytes o 1024 bytes. El usuario simplemente abre el archivo y realiza el comando de escritura. El controlador manejará los detalles y aislará al usuario de las complejidades y riesgos de programar directamente sobre el dispositivo de hardware. Estos controladores proveen la representación de los dispositivos a través de archivos, en GNU/Linux y sistemas operativos Unix todo hardware es representado por un archivo.

Linux posee la capacidad de agregar y quitar componentes del kernel en tiempo de ejecución. Como hemos descripto anteriormente, el kernel Linux posee una estructura de kernel monolítico, con una interfaz para agregar y quitar módulos de controladores de dispositivos dinámicamente luego del arranque del mismo. Esta característica no solo agrega flexibilidad al usuario, sino que además, en sistemas embebidos adquiere una especial importancia debido a su capacidad de actualización y adaptación a dispositivos de E/S nuevos.

3. Sistema de archivos raíz

Todo dispositivo, ya sea que se encuentre en un sistema embebido o una PC de escritorio, necesita al menos un sistema de archivos. Dos razones que describe Yaghmoun son las siguientes:

 Las aplicaciones poseen programas separados, independientes por ende necesitan espacio de almacenamiento en un sistema de archivos.

De esto se desprende la necesidad de poseer un sistema de archivos maestro, un sistema de archivos raíz (RFS, del inglés Root Filesystem).

El RFS es una estructura de directorios jerárquica en donde se almacenan las aplicaciones, librerías y archivos relacionados para ejecutar el sistema. Estos archivos pueden ser binarios, contener solo datos o también vincularnos con estructuras de datos haciendo de nexo con los dispositivos de E/S que hemos descripto en el punto anterior.

El RFS de un sistema Linux embebido y de un Linux de escritorio o servidor no varían demasiado, solo que el primero es reducido por evitar un consumo excesivo de recursos. Este sistema de archivos raíz es montado al momento del arranque de Linux.

Posee una estructura en forma de árbol, en donde todos los directorios se desprenden del directorio principal denominado raíz y simbolizado con una barra inclinada (/). La siguiente figura nos muestra este tipo de estructura.

4. Compilación nativa y cruzada

En el proceso de desarrollo de un sistema GNU/Linux embebido se debe realizar en un primer punto las configuraciones correspondientes de los componentes que formarán parte del sistema embebido (kernel, los módulos del mismo, el sistema de archivos raíz, etc), luego de esto, el paso previo a la prueba del sistema es la etapa de compilación.

Cuando se realiza el desarrollo de una aplicación, usualmente se compila en una computadora tipo PC, ya que dicha aplicación será ejecutada por un sistema de características de hardware similares. Otra práctica habitual ocurre cuando se desea añadir soporte extra al kernel Linux, ya sea para hardware o para protocolos de red, en este caso se realiza la compilación en la misma computadora donde luego será ejecutado.

Este tipo de compilación, en donde el software es compilado y ejecutado en una misma arquitectura de hardware se denomina compilación nativa. Esta alternativa es la más utilizada, y se la denomina de este modo aún si la aplicación ha sida compilada en un equipo diferente al que luego la ejecutará siempre y cuando la arquitectura de hardware sean compatibles. Un ejemplo de esto son las aplicaciones compatibles para microprocesadores AMD e Intel. En el caso de los equipos que frecuentemente se utilizan para sistemas embebidos, poseen recursos de hardware limitados y específicamente diseñados para realizar cierto tipo de tareas. Por este motivo, en general, no es una buena alternativa compilar un sistema completo utilizando el hardware del sistema

embebido.

En este punto es donde surge la necesidad de realizar la compilación del sistema embebido en una computadora cuyos recursos no sean escasos. Es común hoy en día tener una PC capacidades de procesamiento de 3 Ghz y 2GB de memoria RAM, lo que supone una gran ahorro de tiempo al momento de realizar pruebas y cambios de configuraciones, solo basta diseñar un "ambiente" que le permita al compilador producir código ejecutable para un microprocesador diferente al que se está utilizando.

La compilación de software que será ejecutado en una arquitectura diferente, por ende incompatible, a la que está produciendo el código ejecutable se denomina compilación cruzada y este "ambiente" que permite realizar la misma se denomina entorno de compilación cruzada o entorno de desarrollo cruzado. Yaghmoun describe este proceso identificando al equipo que realiza la compilación mediante el término Host o Huesped y al dispositivo que ejecuta el software, como sistema Target u Objetivo.

5. Entorno de compilación cruzada

Para implementar un entorno de compilación cruzada es necesario un conjunto de librerías, utilitarios y binarios. En la bibliografía relacionada con sistemas GNU/Linux embebido a este conjunto de componentes se los denomina toolchain

components.

Estos componentes son:

 Compilador C : compilador de C básico, generador de código objeto (tanto del kernel como de aplicaciones)

 Librería C: implementa las llamadas al sistema mediante APIs.

 Binutils: conjunto de programas necesarios para la compilación, enlazado, ensamblado y depuración de código. Entre otros, los binarios principales son: ld (GNU linker), as (GNU assembler).

Lección 12: uCLinux.

Pronunciado ”you-see-linux”, el nombre de µClinux viene de la combinación de la letra griega µ con la letra C y el nombre Linux. µ designa pequeño o micro, C indica controlador y Linux obviamente del popular sistema operativo. µClinux fue portado inicialmente en el procesador Motorola DragonBall MC68328. El primer sistema objetivo con µClinux fue una PalmPilot usando la board TRG SuperPilot. µClinux es un derivado del kernel 2.0 de Linux destinado para microcontroladores y microprocesadores sin unidades de administración de memoria (MMUs). µClinux hoy en día incluye las versiones 2.4 y 2.6 del kernel de Linux con las debidas modificaciones o extensiones. Incluso, gracias a la popularidad que están tomando

los sistemas embebidos, µClinux ha sido incluido en la versión principal del kernel de Linux, la 2.6.

El hecho de que µClinux haya sido creado para soportar microprocesadores sin MMU, hace que la multitarea sea difícil de implementar. La mayoría de los archivos binarios y código fuente del kernel han sido reescritos para compactar y reducir el código base. Todo esto significa que el kernel de µClinux es mucho más pequeño que el kernel original de Linux 2.0, mientras que mantiene las principales ventajas de este último como son: estabilidad, capacidad superior en redes, y excelente soporte en el sistema de archivos. Entre las características que sobresalen a primera medida se puede destacar que µClinux cuenta con API de Linux común, además de tener un tamaño muy pequeño, de hecho menor a los 512 KB cuando se ha compilado. µClinux viene equipado con un stack completo TCP/IP, junto con el soporte para muchos protocolos de red adicionales. La mayoría de los protocolos de red están implementados y son funcionales.

Además, es un sistema operativo apto para Internet y sistemas embebidos, donde no se necesita de una arquitectura de alto desempeño. Se tiene soporte para varios sistemas de archivos tales como: NFS, ext2, fat32, romfs, jffs y muchos más gracias al sistema de archivos virtual que desciende de Linux.

1. Razones para usar µClinux

Las siguientes características muestran porque µClinux puede ser usado en aplicaciones embebidas de alta complejidad con limitantes en la arquitectura.

 Linux: Conectividad IP incluida, fiabilidad, portabilidad, manejo de numerosos sistemas de archivos, software libre o gratuito.

 Peso liviano: se puede obtener un kernel de Linux 2.6 en menos de 300kb, además, los binarios son mucho más pequeños con la librería µClibc.

 Ejecución en el lugar (XIP): No se necesita cargar los ejecutables en la memoria RAM ya que se pueden correr directamente desde la memoria ROM. Sin embargo la ejecución será más lenta que si lo ejecuta normalmente.

 Más barato: Los núcleos ARM sin MMU son aproximadamente un 30% más pequeños. Un gran número de aplicaciones en sistemas embebidos no necesitan MMU.

 Rápido: con µClinux, los cambios de contexto son bastante rápidos.

 Acceso del usuario al hardware: Las aplicaciones de usuario pueden acceder al sistema entero, incluyendo registros de dispositivo.

 APIs de Linux completas: Se pueden usar la mayoría de llamadas de sistema con algunas excepciones. Las aplicaciones que vienen con la distribución µClinux ya han sido portadas.

 Características completas del kernel 2.6: Estabilidad, núcleo apropiativo, drivers, entre otros.

 Multitarea: Soporte completo para ejecución de tareas múltiples. Claro está, con algunas limitaciones.

 Procesadores soportados: M68K, ARM7, MIPS, entre otros.

µClinux se usa especialmente en procesadores sin MMU. Incluso, en algunos casos es mejor usarlo en procesadores con MMU en lugar de Linux por razones de desempeño, ya que desactivar esta unidad puede traer mejoras en el rendimiento de aplicaciones orientadas a sistemas embebidos. Aunque una gran cantidad de trabajo ya se ha hecho y la mayoría de aplicaciones ya han sido exportadas, alguna experiencia o aprendizaje es definitivamente necesaria cuando se va a iniciar un proyecto nuevo usando µClinux.

2. Diferencias entre Linux y µClinux

µClinux proviene del sistema operativo Linux. En vista de que este sistema operativo soporta procesadores que no cuentan con MMU, varias son las diferencias que existen entre él y su padre.

 No hay administración de memoria virtual: La diferencia definitiva y más prevaleciente entre µClinux y Linux es la falta de administración de memoria virtual (VM). Bajo Linux, la administración de memoria virtual es llevada a través de la unidad MMU que los procesadores tienen. µClinux ha sido creado para sistemas que no cuentan con tal unidad y por lo tanto no hace uso de memoria virtual.

 Diferencias en el kernel: µClinux tiene algunas diferencias en su kernel muy relacionadas principalmente por el hecho de no haber una MMU en el procesador. Por ejemplo, no se podrá hacer uso del soporte de paginación que ofrece una unidad de MMU. El sistema de archivos TMPFS no funciona en µClinux debido a que él confía en las características que la VM le puede brindar. Similarmente, los formatos estándar de ejecutables (elf, a.out, etc.) no funcionan ya que estos también hacen uso de la VM que no está disponible en µClinux. Para solventar este problema, los archivos ejecutables deben tener un formato plano, el cual es un formato ejecutable condensado que almacena solo código ejecutable y datos, además de las reubicaciones necesarias para cargar el ejecutable en memoria.

 Asignación de memoria: µClinux ofrece una elección de dos asignadores de memoria del núcleo. Al principio puede no parecer obvio por qué es necesario un asignador alterno de memoria del núcleo, pero en los sistemas µClinux la diferencia es clara. El asignador predeterminado del núcleo bajo Linux es un método de asignación basado en potencias de dos. Esto le permite operar más rápido y encontrar velozmente áreas de memoria del tamaño correcto para satisfacer peticiones de asignación. Desafortunadamente, bajo µClinux, las aplicaciones deben ser cargadas dentro de la memoria que está fuera del alcance de este asignador. Para entender las consecuencias de esto, especialmente para asignaciones grandes, considérese una aplicación que requiera una asignación de 33KB para ser cargada; realmente se le asigna la siguiente potencia de dos, que es 64KB. Los 31KB de espacio adicional asignado no pueden ser utilizados eficazmente.

Este orden de desperdicio de memoria es inaceptable en la mayoría de sistemas µClinux. Para remediar este problema, un asignador alternativo de memoria se le ha creado al kernel de µClinux. Este es comúnmente conocido como page alloc2() o kmalloc2(), dependiendo de la versión del núcleo.

 Aplicaciones y procesos: Otra diferencia entre Linux y µClinux es la falta de la llamada de sistema fork(). Esto puede requerir bastante trabajo de parte del desarrollador cuando está portando aplicaciones que usan fork(). La única opción bajo µClinux es usar vfork().

3. Librería estándar C

El SO Linux hace uso de la librería estándar C junto con un gran número de librerías tanto estáticas como dinámicas que permiten a las aplicaciones hacer uso de los diferentes servicios que ofrece el SO. La librería C para Linux llamada glibc es de gran tamaño y por lo tanto no es apta para un sistema embebido que por lo general está limitado en memoria.

Por fortuna el proyecto µClinux ha creado la librería µClibc, la cual cumple en gran parte, con la funcionalidad de la librería tradicional pero con un tamaño mucho menor. Actualmente µClibc es mantenido por un proyecto aparte de nombre similar.

4. Distribución µClinux

Hoy en día, µClinux se puede encontrar como una distribución, es decir, no solo viene el código del kernel sino también una serie de aplicaciones ya portadas para él, además de configuraciones para una gran variedad de procesadores y vendedores de sistemas de desarrollo para µClinux. También existe en esta distribución librerías para µClinux como µClib, entre otros. La distribución está en