UNIVERSIDAD CENTRAL MARTA ABREU DE LAS VILLAS FACULTAD DE MATEMÁTICA - FÍSICA - COMPUTACIÓN LICENCIATURA EN CIENCIAS DE LA COMPUTACIÓN

TRABAJO DE DIPLOMA

Plugin para la compilación de Fiasco.OC en Eclipse.

Autor: Rafael Torres Yera Tutores: Ing. Waldo Paz Rodríguez Lic. Alexy Gallardo Segura

Santa Clara

2015

“Año 57 de la Revolución”

DICTAMEN

Hago constar que el presente trabajo de diploma fue realizado en la Universidad Central ―Marta Abreu‖ de Las Villas como parte de la culminación de estudios de la especialidad de Licenciatura en Ciencia de la Computación, autorizando a que el mismo sea utilizado por la Institución, para los fines que estime conveniente, tanto de forma parcial como total y que además no podrá ser presentado en eventos, ni publicados sin autorización de la Universidad.

Firma del Autor

Los abajo firmantes certificamos que el presente trabajo ha sido realizado según acuerdo de la dirección de nuestro centro y el mismo cumple con los requisitos que debe tener un trabajo de esta envergadura referido a la temática señalada.

Firma del Autor Firma del Jefe de Departamento donde se defiende el trabajo

Firma del Responsable de Información Científico-Técnica

Pensamiento

PENSAMIENTO

Los que no tienen el valor de sacrificarse, han de tener al menos,

el valor de callar ante los que se sacrifican.

José Martí. Dedicatoria

DEDICATORIA

Dedicado a mi madre Edelmira Yera Pérez,

A mi padre Rafael Torres Leco,

Y a mi tía Margarita Yera Pérez.

Agradecimientos

AGRADECIMIENTOS

A mi familia, en especial a mis padres y mis hermanos por estar siempre a mi lado y brindarme todo su apoyo,

… a mis abuelos, tíos y primos en especial a mi tía Margarita y primos Yenia y Yenier,

… a todos ellos por su ayuda, apoyo, consejos y contribuir a hacer de mí una persona mejor.

A Yilena por brindarme incondicionalmente todo su amor y cariño, por estar siempre a mi lado y ser motivo de mi inspiración.

A mis suegros y cuñado por hacerme uno más en su familia.

A mi tutor Waldo Paz Rodriguez y a Reinier Millo Sánchez por todo su apoyo y dedicación.

A mis amigos en especial a Liset, Michel, Ediesky, Alexey, Jorge y Ramoncito por su amistad y confianza.

A todos mis compañeros que durante cinco años compartimos la maravillosa etapa de la universidad y otros que lamentablemente no continuaron,

… gracias a ellos por su amistad, los buenos y malos momentos vividos, las largas noches de estudio, en fin todos forman parte indispensable de mí.

A todos los profesores que he tenido a lo largo de mis estudios, en especial a las profesoras Maria y Yanelys.

A todos los trabajadores de la XETID por a cogerme como uno más.

A todas las personas que de una forma u otra me han brindado su apoyo para poder hacer sueños realidades en especial a Ariel.

Gracias a todos. Resumen

RESUMEN

El desarrollo de Sistemas Operativos es una tarea que requiere conocimientos de hardware y software, es por eso que sus desarrolladores necesitan de herramientas capaces de abstraerlos de los recursos de hardware para facilitarles dicha tarea. Fiasco.OC es un desarrollado por la Universidad Técnica de Dresden y pertenece a la familia L4. Este tiene soporte para tareas que requieran tiempo real, para la paravirtualizacion, etc.; pero carece de herramientas con ambientes de desarrollo integrado que permitan automatizar su proceso de compilación, ya que las herramientas actuales de este microkernel realizan este proceso de forma manual mediante la ejecución de comandos en interfaces de consola. En este trabajo se propone el plugin Fiasco.OC Compilator para la plataforma Eclipse que permite automatizar dicho proceso mediante la gestión de configuraciones de compilación. Para comprobar las funcionalidades implementadas se le hicieron varias pruebas al plugin y además se comprobó su integración con el plugin Fiasco.OC Editor y la plataforma Eclipse.

Abstract

ABSTRACT

Operating Systems development is a task that requires knowledge of hardware and software, that is why its developers need tools capable of abstracting hardware resources to facilitate this task. Fiasco.OC is a microkernel developed by the Technical University of Dresden and belongs to the L4 family. This has support for multitask, multicore, real time requiring, paravirtualization, etc .; but it lacks tools with integrated development environments to automate their build because the current tools of this microkernel perform this process manually by executing commands in console interfaces. In this work it proposed the plugin Fiasco.OC Compilator for the Eclipse platform that automates this process by managing build configurations. In addition to test the features implemented several benchmarks were executed to the plugin and also its integration with the Fiasco.OC Editor plugin and Eclipse platform was proven.

Tabla de Contenidos Tabla de Contenidos ...... 8 INTRODUCCIÓN ...... 13 1. MARCO TEÓRICO ...... 5 1.1 Fiasco.OC ...... 5 1.1.1 Framework para el desarrollo utilizando el microkernel FiascoOC ...... 6 1.1.2 Compilación del microkernel FiascoOC ...... 6 1.2 Kconfig ...... 7 1.2.1 Jerarquías ...... 7 1.2.2 Config/Menuconfig...... 7 1.2.3 Atributos ...... 8 1.2.4 Choice ...... 9 1.2.5 Inclusión de archivos ...... 9 1.2.6 Sentencia if ...... 9 1.2.7 Restricciones Lógica ...... 10 1.3 Herramientas para el procesamiento del lenguaje Kconfig ...... 11 1.3.1 Undertaker ...... 11 1.3.2 KConfig Reader + KConfig Reader (XML) ...... 12 1.3.3 LVAT ...... 12 1.4 ANTLR4 ...... 13 1.4.1 Alterar el analizador con predicados semánticos ...... 16 1.4.2 Reconocer múltiples dialectos del lenguaje ...... 16 1.4.3 Reconocer ambigüedades ...... 17 1.5 Eclipse ...... 18 1.5.1 Principales características ...... 19 1.5.2 Arquitectura de la plataforma de Eclipse ...... 19 1.5.3 Plataforma ...... 20 Ayuda ...... 21 1.6 Eclipse CDT ...... 22 1.7 Conclusiones del Capítulo ...... 23 2. DISEÑO E IMPLEMENTACIÓN ...... 24

2.1 Gramática para el lenguaje Kconfig ...... 24 2.2 Estructura TreeKconfig ...... 28 2.3 Patrones de diseño ...... 30 2.3.1 Patrón de diseño Observer ...... 31 2.3.2 Patrón de diseño Singleton ...... 33 2.4 Diagrama de casos de usos ...... 33 2.5 Diagrama de actividades ...... 35 2.6 Diagrama de clases ...... 36 2.7 Diagrama de paquetes ...... 39 2.8 Descripción del plugin Fiasco.OC Compilator ...... 41 2.9 Conclusiones del capítulo ...... 42 3. PRUEBAS Y RESULTADOS ...... 42 3.1 Pruebas para la validación de la gramática Kconfig.g4 ...... 42 3.1.1 Microkernel seL4 ...... 42 3.1.2 Microkernel Fiasco.OC ...... 44 3.2 Pruebas de integración con el plugin Fiasco.OC Editor...... 46 3.3 Pruebas de funcionamiento del plugin Fiasco.OC Compilator...... 47 3.3.1 Compilando el microkernel Fiasco.OC ...... 49 3.4 Conclusiones del Capítulo ...... 51 CONCLUSIONES ...... 53 RECOMENDACIONES ...... 55 REFERENCIAS BIBLIOGRAFICAS ...... 56 ANEXOS ...... 58

Lista de Figuras

Lista de Figuras Figura 1.1 Segmento de un archivo escrito en el lenguaje Kconfig, no se muestran todos los elementos del lenguaje (Informatik-berichte et al. 2015)...... 10 Figura 1.2 Gramática recursiva indirecta a la izquierda...... 14 Figura 1.3 Regla recursiva a la izquierda...... 14 Figura 1.4 Parte de la secuencia del Parse-TreeListener (Parr 2013)...... 15 Figura 1.5 Secuencia completa del Tree-ParserListener (Parr 2013)...... 15 Figura 1.6 Secuencia completa del Tree-ParserVisitors (Parr 2013)...... 16 Figura 1.7 Activa tipos enumerados, dependiendo del predicado semántico...... 17 Figura 1.8 Grafo (Parr 2013)...... 17 Figura 1.9 Regla con predicados semánticos...... 18 Figura 1.10 Grafo (Parr 2013)...... 18 Figura 1.11 Arquitectura de Eclipse (Business & Corp 2006)...... 20 Figura 2.1 Símbolo de tipo bool...... 24 Figura 2.2 Símbolo con más de un tipo...... 25 Figura 2.3 Símbolo con atributo no valido para su tipo...... 25 Figura 2.4 Regla que define los atributos de los símbolos...... 26 Figura 2.5 Regla que define el atributo type...... 27 Figura 2.6 Regla que define el atributo prompt...... 27 Figura 2.7 Regla que define el atributo select...... 27 Figura 2.8 Reglas que definen los tipos tristate y bool...... 28 Figura 2.9 Representación gráfica de la estructura TreeConfig...... 29 Figura 2.10 Diagrama de clases de la estructura TreeConfig...... 30 Figura 2.11 Ejemplo de símbolos dependendientes...... 32 Figura 2.12 Árbol de representación del patrón Observer...... 33 Figura 2.13 Diagrama de casos de usos...... 34 Figura 2.14 Diagrama de actividades para el caso de uso gestionar compilación...... 36 Figura 2.15 Diagrama de clases del plugin...... 38 Figura 2.16 Diagrama de paquetes del plugin...... 39 Figura 2.17 Integración del plugin Fiasco.OC Compilator (Business & Corp 2006)...... 41 Figura 3.1 Microkernel seL4. ARM activado...... 43 Figura 3.2 Microkernel seL4. X86 activado...... 43 Figura 3.3 Comparando plugin con menuconfig...... 44 Figura 3.4 Comparando los globalconfig.out...... 45 Figura 3.5 Comparando los globalconfig.h ...... 45 Figura 3.6 Proyecto Fiasco.OC creado en Eclipse...... 46 Figura 3.7 Proyecto Fiasco.OC para ia32...... 47 Figura 3.8 Funcionalidades del plugin Fiasco.OC Compilator...... 48 Figura 3.9 Gestionar configuraciones de compilación...... 48 Figura 3.10 Directorio build...... 49 Lista de Figuras

Figura 3.11 Directorio de compilación ia32...... 49 Figura 3.12 Funcionalidades del plugin...... 50

INTRODUCCIÓN

INTRODUCCIÓN El desarrollo de la ciencia y tecnología ha puesto al alcance de la sociedad revolucionarias tecnologías, que van desde las computadoras, teléfonos inteligentes, hasta simples equipos electrodomésticos útiles en el hogar. Estos equipos generalmente están controlados por software especializados que son capaces de explotar eficientemente su hardware y brindar a los usuarios una forma sencilla, amena y eficiente de interactuar con estas tecnologías, debido a que tanto el desarrollo como la explotación de estos hardware en sus niveles más bajos es una tarea compleja, incluso para los especialistas y desarrolladores.

Un sistema operativo es un programa que gestiona el hardware de un ordenador proporcionando a los programadores de aplicación un conjunto abstracto de recursos simples, en vez de los complejos recursos del hardware y administra estos recursos. También interactúa como intermediario entre el usuario del ordenador y el hardware del equipo. Los sistemas operativos ocultan el hardware feo con abstracciones hermosas (SILBERSCHATZ et al. 2013).

El kernel o núcleo del sistema es una parte indispensable y por lo tanto la más importante de un sistema operativo. El mismo es una colección de módulos de software que se ejecutan de forma privilegiada y tienen acceso a todos los recursos del sistema (Roch 2004). Es el encargado de mediar toda la comunicación entre la capa de software y la capa de hardware. Este accede directamente a todos los dispositivos del hardware y es el encargado de controlar el acceso al mismo. El acceso al hardware es sumamente complejo y tiene que hacerse de forma segura, por lo que el kernel brinda un grupo de abstracciones para facilitar su acceso. Dentro de las funcionalidades más importantes del kernel se encuentran la administración de memoria para todos los procesos, la administración del tiempo del procesador que estos procesos utilizan y los accesos a los periféricos/elementos y hardware de entrada y salida de forma práctica y cómoda (Tanenbaum 2009).

Los kernel se pueden clasificar en cuatro grupos atendiendo a su diseño: kernel monolítico, microkernel, kernel híbrido y , aunque los más implementados e investigados son los kernel monolítico y los microkernel.

Los kernel monolíticos se consideran hasta ahora como el modelo más común, todo el sistema operativo se ejecuta como un solo programa en modo kernel. El sistema operativo se escribe como una colección de procedimientos, enlazados entre sí en un solo programa binario ejecutable (Tanenbaum 2009). A diferencia de otros enfoques de desarrollo de kernel del sistema, los kernel monolíticos son más fáciles de diseñar correctamente y el código para el control del sistema es mucho más sencillo ya que todos los elementos se encuentran en un mismo espacio de direcciones, el espacio de direcciones del kernel. Aunque por otra parte el tamaño del código fuente, expresado en líneas de código (LOC), es considerablemente grande, lo que hace su comprensión más compleja (Roch 2004), y los hace más vulnerable a la existencia de errores que pueden provocar la falla del sistema en su totalidad. También cuando se le realiza alguna modificación, es necesario recompilar el código fuente del kernel por completo. La implementación más conocida de kernel monolítico es el kernel de Linux. Este desde sus inicios es un kernel monolítico, aunque ha evolucionado y actualmente es modular, o sea, extensible mediante módulos cargables en tiempo de ejecución, pero continúa siendo un kernel monolítico (Love 2010). Por su arquitectura modular, portabilidad y soporte para gran variedad de dispositivos de hardware han permitido su empleo en sistemas de propósito general hasta en sistemas embebidos o de propósitos específicos. Mientras que la idea básica detrás del diseño de microkernel es lograr dividir el sistema operativo en módulos pequeños y bien definidos, sólo uno de los cuales se ejecuta en modo kernel y el resto se ejecuta como procesos de usuario ordinarios. Los microkernel tienen un enfoque de desarrollo minimalista, donde se debe implementar a nivel del kernel solo los elementos principales que son nombrados conceptos o primitivas. En (Liedtke 1995) se definen cuatro primitivas necesarias y suficientes para el correcto desarrollo de un microkernel : espacio de direcciones, abstracción de procesos, mecanismo de comunicación e identificadores únicos. Una de las principales ventajas de los microkernel es la extensibilidad del sistema. En un sistema que emplea un microkernel se pueden adicionar nuevas funcionalidades al sistema sin afectar la funcionalidad del mismo y sin tener la necesidad de recompilarlo, pues las funcionalidades se implementan a nivel de usuario y se interactúan con ellas a través del

mecanismo de comunicación. Otra de las principales ventajas de este enfoque es la recuperación rápida de ante fallos, principalmente en los controladores de dispositivos. En los microkernel estos controladores son implementados a nivel de usuario por lo que un error en alguno de ellos puede que detenga su funcionamiento pero no el del sistema. La comunicación ha sido un aspecto crítico en el desarrollo de los microkernel y es conocido como el cuello de botella en el rendimiento. En los inicios del desarrollo de los microkernel se pensó que estos no alcanzaban el rendimiento esperado por la ineficiencia del mecanismo de comunicación pero en (Liedtke 1995) se demuestra que el bajo rendimiento era producto de mal diseño e implementación. Ambos enfoques de diseño de kernel han sido empleados en sistemas embebidos, pero los microkernel brindan un mejor aprovechamiento del hardware. A diferencia de los kernel monolíticos los microkernel no brindan una capa de atracción para la interacción con el hardware, estos se implementan de forma específica y optimizada, logrando alcanzar altos niveles de rendimiento. Existen varios microkernel entre ellos Minix 3, Fiasco, Fiasco.OC, entre otros. FiascoOC es un microkernel que pertenece a la familia L4 desarrollado por el grupo de sistemas operativos del TU-Dresden (TUDOS). Con soporte para tiempo real y varias arquitecturas y plataformas. Para el desarrollo de sistemas operativos es de vital importancia los ambientes de desarrollos integrados (IDE), pues brindan a los desarrolladores facilidades de edición y navegación por del código fuente, compilación, depuración, entre otras muchas más. Existen varios IDE de código abierto que gozan de preferencia por los desarrolladores, entre los que se encuentra Eclpise, NetBeans y QtCreator.

La Empresa de Tecnologías de la Información para la Defensa (XETID) posee un centro de investigación y desarrollo de software que radica en el Centro de Estudios de Informática de la Universidad Central ―Marta Abreu‖ de Las Villas. Uno de los proyectos que se desarrollan en el mencionado centro está dirigido al desarrollo de sistemas operativos embebidos con tecnologías microkernel y se está utilizando el microkernel Fiasco.OC y el IDE Eclipse para el desarrollo. Las herramientas de configuración y compilación que brinda el microkernel Fiasco.OC trabajan a través de interfaces de

consola, por lo que no brindan a los desarrolladores facilidades de integración con ambientes de desarrollo integrado (IDE). Debido a lo antes expuesto se plantea el siguiente problema de investigación: La ausencia de un IDE que brinde a los desarrolladores integración con el microkernel FiascoOC para su configuración y compilación.

Para dar solución al problema científico se plantea como objetivo general de esta tesis: Diseñar e implementar un plugin para automatizar el proceso de configuración y compilación del microkernel Fiasco.OC en un ambiente de desarrollo integrado.

Este objetivo se desglosa en los siguientes objetivos específicos: • Definir una EDA para el almacenamiento, manejo de la lógica del lenguaje Kconfig e interfaz para su acceso. • Crear y utilizar configuraciones predeterminadas. • Diseñar e implementar un plugin para integrar en Eclipse el proceso de compilación del microkernel Fiasco.OC.

Para la solución al problema de investigación y a los objetivos específicos de esta tesis se dará respuesta a las siguientes preguntas de investigación: • ¿Cómo extender las funcionalidades de Eclipse para integrarlo con el mecanismo de configuración y compilación del microkernel Fiasco.OC? • ¿Cómo identificar los errores durante el proceso de compilación?

Este documento está estructurado en tres capítulos. El primer capítulo que recoge la revisión bibliografía del lenguaje Kconfig y las herramientas utilizadas en el desarrollo del plugin. El segundo capítulo que abarca el diseño e implementación del plugin y la descripción del mismo. Por último el tercer capítulo que describe el análisis de las pruebas realizas al plugin.

CAPÍTULO 1. MARCO TEÓRICO

MARCO TEÓRICOMARCO TEÓRICO

1. MARCO TEÓRICO

El presente capítulo, abarca lo referente a la base teórica de esta investigación. Se describen los principales aspectos del microkernel FiascoOC y el proceso de compilación del mismo. Este proceso de compilación es antecedido por la configuración de las opciones de compilación. Estas configuraciones se realizan a través de archivos escritos en el lenguaje Kconfig, de este lenguaje se realiza un estudio. Además se realiza un análisis de las herramientas ANTLR 4 y el IDE Eclipse. ANTLR 4 es utilizada para el reconocimiento y análisis del lenguaje Kconfig y el IDE Eclipse para el desarrollo del plugin.

1.1 Fiasco.OC

El microkernel Fiasco.OC fue desarrollado en el grupo de sistemas operativos del TU- Dresden, el mismo pertenece a la tercera generación de microkernel y está basado en el microkernel Fiasco de la familia L4, al cual añade un diseño basado en capacidades de objetos. Esta desarrollado generalmente en el lenguaje /C++ con un dialecto de preprocesamiento. Además cuenta con una lista de distribución que permite la interacción con una comunidad activa de desarrolladores, lo cual beneficia el intercambio científico y a la vez sirve como sistema de consulta. Ha sido portado para la arquitectura x86 y ARM en varias versiones y plataformas de hardware. Este microkernel provee soporte para la paravirtualización y tiene soporte para la planificación de tareas e hilos de ejecución en tiempo real, con un soporte de prioridades, lo cual permite que pueda ser empleado en sistemas de tiempo real.

De forma general el microkernel implementa las abstracciones y mecanismos propuestos en (Liedtke 1995), centrados en el manejo de la memoria, la planificación de las tareas y la comunicación entre los procesos y servicios del sistema. En Fiasco.OC todo es considerado un objeto, dividiendo las abstracciones implementadas en siete objetos, también llamados objetos de kernel:  Task: objeto kernel para representar un proceso o tarea del sistema. Internamente define y controla el espacio de direcciones donde se ejecuta el proceso.

5

MARCO TEÓRICOMARCO TEÓRICO

: objeto kernel para representar un hilo de ejecución perteneciente a un proceso o tarea.  IPC Gate: objeto kernel para representar un canal de comunicación entre dos objetos. Este canal de comunicación es empleado para comunicar objetos a nivel de usuario, a nivel de kernel y objetos en diferentes niveles.  IRQ: objeto kernel para el control de las interrupciones del sistema, tanto de hardware como de software.  Scheduler: objeto kernel encargado de controlar la planificación de la CPU entre las tareas e hilos del sistema.  Vcon: objeto kernel para la interacción con el sistema a través de una consola. Este objeto puede ser empleado para la depuración del sistema.  Factory: objeto kernel que permite la creación de otros objetos kernel.

1.1.1 Framework para el desarrollo utilizando el microkernel FiascoOC

Para el desarrollo de sistema operativos empleando Fiasco.OC como microkernel existen dos frameworks de desarrollo, L4Re (TU-DresdenOSGroup 2015) y Genode (Feske 2015). L4Re provee a Fiasco.OC de un conjunto de bibliotecas y servidores para el desarrollo de nuevas aplicaciones. Por otra parte Genode desde sus inicios fue concebido como un framework para el desarrollo de sistemas operativos. Es un framework que se integra con varios kernel de sistema, entre ellos Fiasco.OC. Genode provee a Fiasco.OC de un conjunto de bibliotecas y aplicaciones más completa que el L4R (Genode/Labs 2016). Tiene soporte para la integración con el estándar de C/C++, QT5, Python, entre otras; soporte para aplicaciones de interfaces gráficas, gran variedad de bibliotecas.

1.1.2 Compilación del microkernel FiascoOC

El proceso de compilación del microkernel FiascoOC se realiza mediante MakeFile. Para su compilación es necesario crear un directorio de compilación, en el mismo se genera el archivo de configuración Kconfig y el archivo MakeFile para su compilación. Luego de creado el directorio se configuran las opciones de compilación descritas en el archivo de configuración a través del lenguaje Kconfig.

6

MARCO TEÓRICOMARCO TEÓRICO

1.2 Kconfig

Kconfig es un lenguaje textual que fue desarrollado para administrar la variabilidad del kernel de Linux (El-sharkawy et al. 2015). Aunque nunca se convirtió en un proyecto independiente, también se utiliza en otros proyectos; ejemplo de esto es el microkernel FiascoOC.

A pesar de que estos ficheros son una parte esencial del mecanismo de construcción del kernel de Linux. Este lenguaje de descripción es bastante informal y ambiguo, por lo que las investigaciones existentes no siempre cubren su comportamiento real (Informatik- berichte et al. 2015). A continuación se presenta una visión general de la sintaxis del lenguaje textual Kconfig (Informatik-berichte et al. 2015).

1.2.1 Jerarquías

Kconfig ofrece dos posibilidades para estructurar las opciones de configuración jerárquicamente:

1. Menu: cualquier número de opciones de configuración (y otros elementos como opciones) puede estar contenidos por un menú (menu/endmenu). Un submenú también puede contener otros menús. La visibilidad de estos menús se puede restringir con el atributo visible if. Este atributo sólo es aplicable para los menús y restringe el menú completo incluyendo todos los elementos anidados. Sin embargo, estos elementos todavía existen y pueden ser seleccionados o modificados por restricciones o valores por defecto, pero no por el usuario (Figura 1.1 de la línea 1- 14). 2. Restricciones: las sentencias if ofrecen una alternativa para modelar jerarquías. Si la visibilidad de una opción de configuración B depende de otra opción de configuración A y B se escribe directamente por debajo de A en un archivo KConfig, se mostrará en una estructura jerárquica B por debajo de A.

1.2.2 Config/Menuconfig

Estos elementos representan las opciones de configuración, son los más utilizados del lenguaje y pueden ser vistos como ―variables‖ (Figura 1.1 de la línea 7-10). Estas opciones

7

MARCO TEÓRICOMARCO TEÓRICO de configuración pueden ser de los tipos siguientes: tristate, bool, string, hex o int. Todos, menos el primero, se conocen en prácticamente todos los lenguajes de programación típicos y tienen la misma semántica.

Las opciones de configuración tristate se codifican de las siguientes alternativas:

 n (la característica relacionada no serán parte del sistema resultante).  y (la característica relacionada será una parte permanente del sistema resultante).  m (la característica relacionada será compilada como un módulo, lo que significa que puede ser cargado o descargado de forma flexible en tiempo de ejecución).

1.2.3 Atributos

Cualquier opción de configuración pueden enriquecerse con los siguientes atributos (pueden ser condicionales):

 prompt: muestra un identificador para el usuario. Una opción de configuración sin prompt es un símbolo invisible y no se puede modificar directamente (sólo a través restricciones). El prompt puede ser definido con el tipo del símbolo o usando la palabra clave prompt (Figura 1.1 línea 9).  default: especifica los valores predeterminados de una opción de configuración. Estos valores pueden ser cambiados por el usuario si la opción de configuración es visible. Por otra parte, una opción de configuración puede contener cualquier número de valores predeterminados.  range: especifica un límite superior y un límite inferior para las opciones de configuración de tipo int o hex.

KConfig especifica dos tipos de restricciones para restringir los posibles valores de una opción de configuración:

 depends on: se utiliza para describir si una opción de configuración puede ser configurada o está deshabilitada. Contrariamente a los otros atributos, este atributo no puede estar condicionado (Figura 1.1 línea 10).

8

MARCO TEÓRICOMARCO TEÓRICO

 select: este atributo debe ser usado con cuidado, pues forzara a un símbolo a un valor (y) sin evaluar las dependencias. Este atributo es generalmente usado para seleccionar símbolos no visibles (no tienen prompt) y para símbolos que no tengan dependencias. Si se selecciona una opción de configuración en múltiples tiempos, se establece en la mayor selección. Por otra parte, pueden ser condicionados. En tal caso, la opción de configuración seleccionada sólo será cambiada si la variable de selección se cambió y la condición de la restricción se cumplió (Figura 1.1 línea 24).

1.2.4 Choice

Es una elección que agrupa a varias opciones de configuración y sólo pueden ser de tipo bool o tristate. En caso de una elección booleana, exactamente una opción de configuración puede ser seleccionada. Una elección tristate permite la selección de múltiples elementos como módulos. A un choice se le pueden atribuir la mayoría de los atributos mencionados anteriormente y pueden ser opcionales, lo que permite establecer la opción a ―n‖ y ninguna de las opciones de configuración puede ser seleccionada. (Figura 1.1 línea 15-25).

1.2.5 Inclusión de archivos

Kconfig permite dividir un modelo enorme en varios archivos separados. La sentencia source permite incluir el contenido de otro archivo Kconfig en el archivo actual. Esta se compone de la propia palabra seguida de la dirección del fichero que se desea incluir en ese fragmento.

1.2.6 Sentencia if

Es posible agrupar los elementos con if y endif para hacer su existencia en función de una condición. Los desarrolladores del kernel de Linux utilizaron esta sentencia para definir la misma opción de configuración dos veces con diferentes atributos o para la inclusión de diferentes archivos Kconfig dependiendo de la arquitectura (El-sharkawy et al. 2015).

9

MARCO TEÓRICOMARCO TEÓRICO

Figura 1.1 Segmento de un archivo escrito en el lenguaje Kconfig, no se muestran todos los elementos del lenguaje (Informatik-berichte et al. 2015).

1.2.7 Restricciones Lógica

Kconfig utiliza una lógica de tres estados en lugar de una lógica booleana para la crear y evaluar expresiones, además de tener en cuenta el uso de cinco operadores: y (&&), o (||), igual (=), diferente (!=) y el operador de negación (!). Las expresiones se definen con las sintaxis siguientes:

::= Convierte el símbolo en una expresión. Tristate y bool son simplemente convertidos a su respectivo valor, mientras que en los otros tipos símbolos, el resultado es 'n'.

'=' Si los valores de los símbolos son iguales devuelve 'y', en otro caso 'n'.  '!='

10

MARCO TEÓRICOMARCO TEÓRICO

Si los valores de los símbolos son iguales devuelve 'n', en otro caso 'y'.  '('')' Devuelve el valor de la expresión, teniendo en cuenta la precedencia.  '!' Devuelve el resultado de (2-/expr/).  '&&' Devuelve el resultado de min(/expr/, /expr/).  '||' Devuelve el resultado de max(/expr/, /expr/).

1.3 Herramientas para el procesamiento del lenguaje Kconfig

A continuación, se muestra una breve descripción de herramientas reportadas en la literatura que se emplean para el procesamiento del lenguaje Kconfig. Estas son mayormente de código abierto y capaces de procesar varios dialectos definidos para el mismo, así como brindar determinadas estadísticas acerca de los elementos del lenguaje.

1.3.1 Undertaker

Undertaker es un conjunto de herramientas desarrolladas para comprobar la estructura de las directivas del preprocesador del kernel de Linux a partir de su modelo de configuración, para encontrar bloques de código, que son permanentemente seleccionados o deseleccionados en todas las configuraciones (Informatik-berichte et al. 2015). Este análisis se realiza en dos pasos. Primero, todos los archivos Kconfig se traducen en modelos lógicos, y posteriormente en el segundo paso, las directivas del preprocesador también se traducen en modelos lógicos y pasan directamente junto con las traducciones lógicas del Kconfig a un solucionador para encontrar código que no es configurable. Undertaker incorpora dos herramientas alternativas para la traducción de Kconfig en una formula booleana.

 dumpconf: es una versión modificada de menuconfig. Esta herramienta traduce los archivos Kconfig primero a un formato intermedio. Esta información es guardada en archivos RSF(*.rfs), que describen la información de los archivos Kconfig de una manera más estructurada. Los archivos RSF principalmente contienen la misma

11

MARCO TEÓRICOMARCO TEÓRICO

información lógica que los archivos Kconfig, pero dumpconf ya suma alguna información adicional para las herramientas de análisis, posteriores.  rsf2model es usado para crear formulas booleanas a partir de archivos RSF generados por dumpconf. Estos archivos son salvados como archivos Model (*.model).  Satyr: es una alternativa para dumpconf + rsf2model. Esta herramienta traduce los archivos Kconfig directamente en DIMACS-format (Makhorin 2011).

1.3.2 KConfig Reader + KConfig Reader (XML)

KConfig Reader fue diseñado para convertir los archivos Kconfig en fórmulas booleanas para el razonamiento (Informatik-berichte et al. 2015). De esta herramienta existen dos versiones:

 KConfig Reader: que produce archivos de RSF como formato intermedio. Esta herramienta utiliza una versión de dumpconf (Undertaker) ajustado para la creación de archivos RSF. Luego estos se utilizan para crear formulas booleanas. Estas fórmulas booleanas se almacenan en archivos model (*.model). Sin embargo, los archivos model generado por KConfig Reader son diferentes a los archivos model generados por Undertaker. KConfig Reader ofrece opcionalmente la posibilidad de crear fórmula CNF (Makhorin 2011), que también se guarda DIMACS-format (Makhorin 2011).  KConfig Reader (XML) para referirse explícitamente a una versión más joven de KConfig Reader. Esta versión se basa en una versión reescrita de la herramienta dumpconf ajustada, que ya es parte de KConfig Reader (XML). Contrariamente a KConfig Reader, esta versión utiliza archivos XML como formato intermedio en lugar de los RSF común. Sin embargo, los archivos XML están siendo nombrados como archivos *.rsf.

1.3.3 LVAT

Las herramientas de análisis de la variabilidad de Linux (LVAT) traducen archivos Kconfig a fórmula CNF (Makhorin 2011) y luego es exportada a un archivo DIMACS, pero LVAT no es capaz de traducir los archivos Kconfig directamente en formato DIMACS

12

MARCO TEÓRICOMARCO TEÓRICO

(Informatik-berichte et al. 2015). En primer lugar, los modelos deben traducirse a un formato intermedio, que simplifica el análisis. Los desarrolladores ofrecen dos herramientas para la generación del formato intermedio:  exconf: traduce ficheros Kconfig a un formato de texto. Este extractor está marcado como compatible con modelos anteriores a la versión 3.0 de Kconfig Linux.  protoconf: traduce ficheros Kconfig a un formato binario y es compatible con las versiones más recientes de Linux.

A pesar de la existencia de estas herramientas para el procesamiento del lenguaje Kconfig, fue necesaria la implementación de una para el correcto funcionamiento del plugin. Para el desarrollo de la misma se utilizó la herramienta ANTLR4.

1.4 ANTLR4

ANTLR4 (Parr 2013) es una herramienta para el reconocimiento de lenguaje empleada como generador de análisis de gran alcance para la lectura, gestión, ejecución o la traducción de texto estructurado y archivos binarios. Ampliamente utilizada para construir lenguajes y herramientas. Esta herramienta es usada en proyectos de primer nivel, como los compiladores de los lenguajes HiveQL y Pig, el ORM Hibernate o Twitter Search, donde ANTLR es usado para analizar más de dos millones de consultas diarias. El IDE NetBeans analiza el lenguaje C++ con ANTLR 4 y Oracle lo usa dentro del IDE Developer SQL y sus herramientas (Parr 2013).

En su cuarta versión tiene nuevas capacidades que reducen la curva de aprendizaje y hace el desarrollo de gramáticas y lenguajes de aplicación mucho más sencillo y ameno. El cambio fundamental en esta versión es que puede aceptar cualquier gramática que se defina, excepto, las recursivas indirectas a la izquierda; en otras palabras las reglas no pueden hacer referencia a otra regla en el lado izquierdo de una alternativa que finalmente regresa para hacer referencia a la regla original sin cumplir ninguna ficha, ver Figura 1.2.

13

MARCO TEÓRICOMARCO TEÓRICO

Figura 1.2 Gramática recursiva indirecta a la izquierda.

El analizador de ANTLR4 emplea la tecnología análisis adaptativo LL(*) o ALL(*) (Parr et al. 2014) para realizar el análisis de la gramática de forma dinámica en tiempo de ejecución, antes de que el analizador generado se ejecute. En el análisis estático, se tiene que considerar todas las posibles (infinitamente largas secuencias de entrada) (Parr 2013). Por otro lado otra característica impresionante de ANTLR4, es que simplifica drásticamente las reglas gramaticales utilizadas para analizar las estructuras sintácticas como las expresiones aritméticas de los lenguajes de programación. La gramática más natural para reconocer expresiones no es válida para generadores tradicionales. Con ANTLR 4 se pueden coincidir expresiones con las reglas que se aprecian en la Figura 1.3.

Figura 1.3 Regla recursiva a la izquierda.

Además de las mejoras relacionadas con la gramática, ANTLR4 hace mucho más fácil construir aplicaciones de lenguajes. El analizador genera automáticamente estructuras de datos basadas en árboles que implementan los patrones de diseño listener y visitor. Estos árboles generados por ANTLR4, se conocen como: Parse-Tree Listeners y Parse-Tree Visitors. La primera se encarga de especificar para cada gramática los métodos de entrada y salida para cada regla, en la Figura 1.4 se puede observar con más detalle cómo funciona el mecanismo de dicha estructura, que comienza cuando se analiza el nodo para la regla assign, por ejemplo, se dispara enterAssign. Se visitan todos los nodos hijos assign, y luego se dispara exitAssign(), como puede observarse este recorrido se realiza primero en profundidad (representado por la línea discontinua gruesa).

14

MARCO TEÓRICOMARCO TEÓRICO

Figura 1.4 Parte de la secuencia del Parse-TreeListener (Parr 2013).

El mecanismo de escucha es automático y nuestros métodos de detección no tienen que explícitamente visitar a sus hijos. En

, se muestra la secuencia completa de llamadas realizadas al oyente.

Figura 1.5 Secuencia completa del Tree-ParserListener (Parr 2013).

15

MARCO TEÓRICOMARCO TEÓRICO

Por otro lado, la estructura Parse-Tree Visitors se emplea en situaciones que se requiere controlar el recorrido en sí, una llamada explícita a métodos para visitar a los hijos. ANTLR4 genera una interfaz de visitante para una gramática con un método de visita por regla, este mecanismo se puede apreciar en la Figura 1.6.

Figura 1.6 Secuencia completa del Tree-ParserVisitors (Parr 2013).

Donde la línea discontinua gruesa muestra el recorrido en profundidad del árbol de análisis sintáctico. Las líneas discontinuas indican la secuencia de llamada los métodos de visitantes.

1.4.1 Alterar el analizador con predicados semánticos

Las acciones especiales, {…}?, se les conoce como predicados semánticos, estos permiten desactivar selectivamente partes de la gramática en tiempo de ejecución. Los predicados son expresiones booleanas que tienen el efecto de reducir el número de opciones que procesa el analizador, lo cual incrementa la capacidad y velocidad de procesamiento del mismo. Hay dos casos de uso común para predicados semánticos. En primer lugar, podríamos necesitar un programa de análisis que maneje múltiples versiones, ligeramente diferentes (dialectos) en el mismo lenguaje; mientras que el segundo caso implica la resolución de ambigüedades gramaticales.

16

MARCO TEÓRICOMARCO TEÓRICO

1.4.2 Reconocer múltiples dialectos del lenguaje

Para emplearlos con esta finalidad el efecto será reconocer diferentes dialectos, según los resultados de la evaluación de expresiones booleanas sobre la marcha. En la

Figura 1.7 se aprecia cómo se puede cambiar el mismo analizador entre permitir y no permitir tipos enumerados.

Figura 1.7 Activa tipos enumerados, dependiendo del predicado semántico.

El predicado {!java5}? permite a enum actuar como un identificador solamente cuando el modo no sea java5. En caso contrario se desactiva la segunda alternativa. Visto como un grafo, quedaría como se muestra en la Figura 1.8.

Figura 1.8 Grafo (Parr 2013).

1.4.3 Reconocer ambigüedades

Las ambigüedades ocurren en un lenguaje debido a que existen situaciones en las que se tiene que seleccionar una sola regla entre varias, teniendo en cuenta que cada alternativa comprende comportamientos diferentes. Es necesario señalar que el tener más de una regla

17

MARCO TEÓRICOMARCO TEÓRICO por la cual coincida una misma frase de entrada en una gramática es casi siempre un error gramatical. En la mayoría de los lenguajes, la sintaxis sola dicta una única forma de interpretar todas las frases válidas. Eso significa que nuestras gramáticas deben coincidir con cada entrada en un solo camino. Si nos encontramos con múltiples interpretaciones, hay que volver a escribir la gramática para eliminar las interpretaciones no válidas.

A continuación, veamos un ejemplo en el lenguaje C++, donde la expresión de T (0) es o bien una llamada a una función o un constructor dependiendo de si T es un nombre de función o un tipo. La expresión es ambigua porque la misma sintaxis se aplica a varias interpretaciones. Para llegar a la interpretación correcta, el analizador necesita desactivar una de las alternativas de acuerdo con la forma en que T se define en el programa. Para ello se tiene dos predicados como se aprecia en la Figura 1.9 que comprueban si ID se trata como el nombre de función o de un tipo (Parr 2013).

Figura 1.9 Regla con predicados semánticos.

Visualmente, la regla expr mostrada en la Figura 1.9 se puede apreciar en la Figura 1.10 su representación a través de un grafo con puntos de corte en la parte delantera de las primeras dos alternativas:

Figura 1.10 Grafo (Parr 2013).

18

MARCO TEÓRICOMARCO TEÓRICO

1.5 Eclipse

La definición que da el proyecto Eclipse acerca de su Software es: ―una especie de herramienta universal – un IDE abierto y extensible para todo y nada en particular‖. Es una plataforma de desarrollo de código abierto basada en Java. Por si misma, es simplemente un marco de trabajo y un conjunto de servicios para la construcción del entorno de desarrollo de los componentes de entrada. Eclipse también incluye el Entorno de Desarrollo de Complementos (PDE), que es de interés principalmente para los desarrolladores que quieren extender sus funcionalidades, dado que les permite construir herramientas que se integran sin dificultades con el propio entorno (Silva 2009).

1.5.1 Principales características

 Perspectivas, editores y vistas: en Eclipse el concepto de trabajo está basado en las perspectivas, que no es otra cosa que una pre configuración de ventanas y editores, relacionada entre sí, y que nos permiten trabajar en un determinado entorno de trabajo de forma óptima.

 Gestión de proyectos: el desarrollo sobre Eclipse se basa en los proyectos, que son el conjunto de recursos relacionados entre sí, como puede ser el código fuente, documentación, ficheros configuración, árbol de directorios, etc.

 Depurador de código: se incluye un potente depurador, de uso fácil e intuitivo, y que visualmente nos ayuda a mejorar nuestro código.

 Extensa colección de plugin: están disponibles en una gran cantidad, unos publicados por Eclipse y otros por terceros. Los hay gratuitos, pagos, bajo licencias, pero casi para cualquier cosa que se imagine tiene el plugin adecuado.

1.5.2 Arquitectura de la plataforma de Eclipse

La Plataforma de Eclipse es un marco de trabajo con un conjunto poderoso de servicios que soporta complementos, como JDT y el Entorno de Desarrollo de Complementos. La misma está compuesta por varios componentes principales como: tiempo de ejecución de la plataforma, Espacio de Trabajo, Entorno de Trabajo, Equipo de Soporte y Ayuda (Business & Corp 2006). Como se muestra en la Figura 1.11.

19

MARCO TEÓRICOMARCO TEÓRICO

Figura 1.11 Arquitectura de Eclipse (Business & Corp 2006).

1.5.3 Plataforma

El tiempo de ejecución de la plataforma es el núcleo que descubre en el inicio qué complementos están instalados y crea un registro de información sobre ellos. Para reducir el tiempo de inicio y el uso de los recursos, no carga ningún complemento hasta que

20

MARCO TEÓRICOMARCO TEÓRICO realmente se lo necesita. Excepto el núcleo, todo lo demás se implementa como un complemento (Eclipse 2015).

Espacio de trabajo

El espacio de trabajo es el complemento responsable de la administración de los recursos del usuario. Este incluye todos los proyectos que crea el usuario, los archivos de esos proyectos y los cambios en los archivos y otros recursos. El espacio de trabajo también es responsable de notificar a otros complementos interesados sobre los cambios en los recursos, como archivos que se crearon, eliminaron o cambiaron.

Entorno de trabajo

El entorno de trabajo proporciona a Eclipse una interfaz de usuario (IU). Se crea con la utilización de un Kit de Herramientas Estándar (SWT) — una alternativa no estándar para el Swing/AWT GUI API de Java — y un API, JFace con un nivel superior, construido por sobre SWT que proporciona componentes de la IU.

SWT se grafica de forma más parecida a las capacidades nativas de los gráficos del sistema operativo subyacente que Swing o AWT, que no solo hace que SWT sea más rápido, sino que también permite que los programas JAVA se parezcan y se sientan más como aplicaciones nativas. El uso de esta nueva API GUI podría limitar la portabilidad del entorno de trabajo de Eclipse y de las aplicaciones que usan esta API, aunque la biblioteca SWT está disponible para los sistemas operativos más populares.

Soporte del equipo

El componente de soporte del equipo es responsable de proporcionar soporte para el control de la versión y la gestión de la configuración. Agrega vistas según sea necesario para permitir al usuario interactuar con cualquier sistema de control de versiones (si hay) que se esté utilizando. La mayoría de los componentes no necesitan interactuar con el componente de soporte del equipo a menos que proporcionen servicios de control de versiones.

Ayuda

21

MARCO TEÓRICOMARCO TEÓRICO

El componente de ayuda pone en paralelo la expansión de la propia Plataforma de Eclipse. De la misma forma que los complementos agregan funcionalidad a Eclipse, la ayuda proporciona una estructura de navegación de complementos que permite a las herramientas agregar documentación en la forma de archivos HTML.

1.6 Eclipse CDT

Los lenguajes C y C ++ son algunos de los lenguajes de programación más populares y ampliamente utilizadas en el mundo, así que no es sorprendente que la plataforma Eclipse proporciona soporte para el desarrollo en C / C ++. Debido a que la plataforma Eclipse no es compatible con C / C ++ directamente, utiliza plugin externos.

Dentro de gran variedad de proyectos basados en la plataforma Eclipse, se encuentra uno específico para el desarrollo en C y C++. Este proyecto es conocido con el nombre de Eclipse CDT o simplemente CDT por sus siglas en inglés, que abrevian ―Eclipse C/C++ Development Tooling” (CDT 2015).

El proyecto CDT inicio en julio de 2002 con el objetivo primordial de proveer un marco de trabajo para el desarrollo en C y C++. El proyecto Eclipse CDT provee un IDE para C y C++ completamente funcional dentro de la plataforma Eclipse. Sus características incluyen creación de proyectos, compilación para varios conjuntos de herramientas, compilación por medio de make, navegación, jerarquía de tipos, árboles de llamada, navegador de encabezado, navegador de definiciones de macros, editor de códigos con resaltado de sintaxis, agrupación de código, herramientas visuales de depuración, entre otras .

Utilizando el CDT es posible realizar introspección de código C o C++. El conocimiento del código fuente es guardado en el DOM (Document Object Model) del CDT, con el cual se construyen varios componentes de introspección (CDT 2015):

 Scanner: reconoce y construye tokens para el parser.

 Parser: reconoce la salida de Scanner y construye ASTs (Abstrac syntax trees).

22

MARCO TEÓRICOMARCO TEÓRICO

 DOM ASTs: árboles que guardan información estructural detallada del código.

 Visitadores: visitan nodos en el AST para hacer minerías de datos.

 Índex: provee la habilidad d ejecutar búsquedas rápidas por nombres de elementos (nombre de variables, nombre de tipo, etc.).

 Visitadores de índex: visitan nodos en el índex para hacer minería de datos.

Debido a su complejidad, el CDT se divide en varios componentes, que adoptan la forma de plugin por separado. Cada componente funciona como un proyecto autónomo, con su propio conjunto de committers, categorías de errores y listas de correo. Sin embargo, se requiere que todos los plugin para que el CDT funcione correctamente. Aquí está una lista completa de los CDT plugin / componentes (CDT 2015):

 Primary CDT plugin: es el más importante, pues provee las capacidades básicas.  CDT Feature Eclipse: proporciona las características de los componentes.  CDT Core: presenta el modelo del núcleo, CDOM, y otros componentes del núcleo.  CDT UI: proporciona los relacionados con la interfaz de usuario, características, puntos de vista, editores, asistentes, etc.  CDT Launch: proporciona mecanismo de lanzamiento para lanzar ejecutables y herramientas externas.  CDT Debug Core: proporciona funciones de depuración.  CDT Debug UI: proporciona las capacidades de interfaz de usuario para los editores de depuración y puntos de vista.  CDT Debug MI: es el conector de aplicaciones para depuradores compatibles con MI.

1.7 Conclusiones del Capítulo

Una vez realizado el estudio del marco teórico de la presente investigación se arribó a las siguientes conclusiones:  Existe la necesidad de un plugin para el IDE Eclipse que facilite a los desarrolladores de la XETID y la comunidad del microkernel FiascoOC su configuración y compilación.

23

MARCO TEÓRICOMARCO TEÓRICO

 La implementación del plugin se desarrollara en el IDE Eclipse.  Se utilizara para el reconocimiento y análisis del lenguaje Kconfig la herramienta ANTLR4.

24

CAPÍTULO 2. DISEÑO E IMPLEMENTACIÓN

DISEÑO E IMPLEMENTACIÓNDISEÑO E IMPLEMENTACIÓN

2. DISEÑO E IMPLEMENTACIÓN En este capítulo se abordara todo lo referente al diseño e implementación del plugin para la configuración y compilación del microkernel FiascoOC. Se definen los casos de uso, se muestran los diagramas de actividades, diagrama de clases y diagrama de paquetes. Además se analiza los patrones de diseño implementados en el plugin y la descripción del mismo.

2.1 Gramática para el lenguaje Kconfig

Para la implementación del plugin se implementó una gramática para analizar los archivos Kconfig. Estos ficheros son necesarios para la configuración del proceso de compilación del microkernel Fiasco.OC, ya que es en donde se almacenan todas las opciones que se pueden configurar para el proceso de compilación.

Para implementar dicha gramática se tomó como referencia la utilizada por las herramientas de compilación que brinda este microkernel. Durante el proceso de análisis de esta gramática se detectaron varios problemas de ambigüedades, pues esta permite opciones que en momentos específicos no deben permitirse según la especificación del lenguaje Kconfig, ejemplo de ello se puede ver en la declaración de los símbolos con el atributo type. Un símbolo puede tener un solo tipo como se aprecia en la Figura 2.1, sin embargo, la gramática descrita en las herramientas del microkernel en su sintaxis permite más de un tipo como se puede apreciar en la Figura 2.2, aunque esto se resuelve en el procesamiento del símbolo tomando como tipo del símbolo, el primero de ellos, esto representa un error de sintaxis en el lenguaje.

Figura 2.1 Símbolo de tipo bool.

24

DISEÑO E IMPLEMENTACIÓNDISEÑO E IMPLEMENTACIÓN

También se detectaron otros problemas, como atributos no aplicables a un símbolo. Como se puede apreciar en la Figura 2.3 donde el símbolo string VAR_A contiene el atributo select aplicable solo a los símbolos tristate y bool.

Figura 2.2 Símbolo con más de un tipo.

Figura 2.3 Símbolo con atributo no valido para su tipo.

En la gramática implementada en el plugin se trata de resolver los problemas detectados en la gramática utilizada por las herramientas de compilación del microkernel FiascoOC, luego de un estudio riguroso de la misma y de la sintaxis del lenguaje. Seguidamente se describirán los fundamentos e implementaciones más importantes de la misma, la especificación general de la gramática se encuentra detallada en el Anexo 1.

Partiendo de que el IDE Eclipse se encuentra desarrollado en Java, se optó por emplear para el reconocimiento del lenguaje la herramienta ANTLR 4, la cual tiene un conjunto de funcionalidades que facilitan el desarrollo de gramáticas. Para resolver los problemas de ambigüedades detectados durante la revisión de la gramática de las herramientas de Fiasco.OC, principalmente en los atributos, se propone utilizar los predicados semánticos dados por ANTRL 4, ya que estos pueden restringir las opciones del parser en tiempo de compilación con lo cual puede solucionar los problemas que presenta la gramática de las herramientas de Fiasco.OC.

25

DISEÑO E IMPLEMENTACIÓNDISEÑO E IMPLEMENTACIÓN

Para dar solución a los problemas detectados se tuvo en cuenta que cada símbolo puede tener un solo atributo type y prompt respectivamente; por lo que la regla para los atributos de un símbolo, queda construida de forma recursiva a la izquierda como se muestra en la Figura 2.4. A pesar de ello, una vez reconocido el atributo type el parser inhabilita esta opción.

Figura 2.4 Regla que define los atributos de los símbolos.

La regla att_type es antecedida por un predicado semántico como se muestra en la Figura 2.5, la variable booleana bit_type inicialmente es verdadera, pero una vez ejecutada la regla esta variable toma valor falso, inhabilitándola, restringiendo esta regla a ser reconocida solo una vez en un símbolo. La variable bit_type toma valor verdadero luego de haber analizado el símbolo en su totalidad dejándola en su valor inicial, habilitando la regla att_type para los símbolos siguientes en el reconocimiento.

26

DISEÑO E IMPLEMENTACIÓNDISEÑO E IMPLEMENTACIÓN

Figura 2.5 Regla que define el atributo type.

El análisis de la regla att_prompt es análoga a la regla att_type descrita anteriormente como se puede apreciar en la Figura 2.6.

Figura 2.6 Regla que define el atributo prompt.

El atributo select es aplicable solo a símbolos bool y tristate, al igual que el atributo range aplicable solo a los símbolos int y hex, dependiendo del tipo de símbolo son habilitados. La regla del atributo select es antecedida por un predicado semántico como se muestra en la Figura 2.7, inicialmente es inhabilitado pues la variable flags_select es inicializada a falso, tomando verdadero una vez reconocido en el símbolo el atributo type y el tipo sea bool o tristate como se puede apreciar en la Figura 2.8 habilitando así esta regla, permitiéndole al símbolo actual reconocer el atributo select.

Figura 2.7 Regla que define el atributo select.

27

DISEÑO E IMPLEMENTACIÓNDISEÑO E IMPLEMENTACIÓN

Figura 2.8 Reglas que definen los tipos tristate y bool.

Todos los problemas de ambigüedad fueron resueltos empleando los predicados semánticos de ANTLR, básicamente a través del mecanismo anteriormente explicado.

2.2 Estructura TreeKconfig

Se diseñó una estructura que almacena la información descrita en los ficheros Kconfig para poder implementar la lógica del lenguaje y mostrar al usuario las opciones de configuración activas en cada momento del proceso.

Debido a que el lenguaje Kconfig tiene una estructura jerárquica, se implementó una estructura de datos basada en árboles a través de un arreglo de Nodos, donde cada Nodo tiene una lista de cada uno de sus hijos, su padre y una serie de atributos útiles para el funcionamiento de la estructura. En la Figura 2.9 el nodo N1 tiene como hijos N2 y Nn y como padre el Nodo N0.

28

DISEÑO E IMPLEMENTACIÓNDISEÑO E IMPLEMENTACIÓN

Figura 2.9 Representación gráfica de la estructura TreeConfig.

La clase Nodo se diseñó como una superclase, pues es la abstracción más general de todos los elementos que conforman el lenguaje, de ella heredan varias clases las cuales representan cada uno de elementos del lenguaje, estos se estructuraron en dos grupos los nodos estructurales y los símbolos.

Los nodos estructurales representan los elementos estructurales del lenguaje choice, menú y sentencias if. Mientras que los símbolos se dividieron en dos grupos: los símbolos constantes y los símbolos no constantes. Los primeros representan solo a los símbolos que forman parte de las expresiones; mientras que los símbolos no contantes son los más usados, ya que son definidos con la sentencia config. Para más detalles ver el diagrama de clases para TreeConfig

Figura 2.10.

29

DISEÑO E IMPLEMENTACIÓNDISEÑO E IMPLEMENTACIÓN

Figura 2.10 Diagrama de clases de la estructura TreeConfig.

2.3 Patrones de diseño

De acuerdo a (Alexander et al. 1977) cada patrón se asocia a un problema que ocurre una y otra vez en nuestro entorno, y entonces describe la solución de ese problema de tal manera que pueda ser utilizada un millón de veces, sin tener que hacer dos veces lo mismo. Aunque (Alexander et al. 1977) se refiere a patrones aplicados al diseño de edificios y ciudades, sus ideas son aplicables a los patrones de diseño orientado a objetos.

Los patrones de diseño orientado a objetos son descripciones de la comunicación de objetos y clases que pueden personalizarse para resolver un problema general de diseño en un contexto particular. En otras palabras, un patrón de diseño da nombre, abstrae e identifica los elementos esenciales de un problema de diseño, su solución y los resultados de su aplicación (Martin 2003).

30

DISEÑO E IMPLEMENTACIÓNDISEÑO E IMPLEMENTACIÓN

2.3.1 Patrón de diseño Observer

El patrón Observer (Kak 2014) es útil si tenemos la necesidad de realizar acciones como consecuencia del cambio de estado o cierta circunstancia de un objeto. El patrón Observer nos permite mantener desacoplados el objeto que emite el evento y el objeto que recibe el evento e independizar al objeto observable del número de observadores que tenga.

En Java este patrón podemos implementarlo usando la clase Observable, y la interfaz Observer proporcionadas en el propio lenguaje. La clase que queremos que reciba los eventos deberá implementar la interfaz Observer y el objeto que queremos que produzca los eventos debe extender o contener una propiedad de tipo Observable. La interfaz Observer contiene un único método de nombre update, que recibe dos parámetros que son la instancia del objeto observable sobre la que se ha producido el evento y un Object a modo de argumento que el objeto observable envía. La clase Observable contiene métodos para añadir y eliminar observadores que queremos que sean notificados, obtener un contador con el número de observadores y unos métodos para conocer y establecer si un objeto ha cambiado con el método hasChanged.

Los elementos del lenguaje Kconfig pueden ser dependientes entre sí. Esta dependencia se refleja a través de sus atributos, en la Figura 2.11 puede verse que el símbolo A depende del símbolo B y en el símbolo B su valor por defecto depende del símbolo C, haciéndolo también dependiente.

31

DISEÑO E IMPLEMENTACIÓNDISEÑO E IMPLEMENTACIÓN

Figura 2.11 Ejemplo de símbolos dependendientes.

La implementación del patrón Observer en la clase Nodo permite actualizar propiedades dinámicamente en la estructura TreeConfig y reflejar los cambios en su representación gráfica, la cual se realiza a través de un TreeView (NG & Mihalkovic 2005).

La Figura 2.12 muestra una representación gráfica del patrón Observer para el ejemplo que se muestra en la Figura 2.11, como se muestra el símbolo C es observado por el símbolo B que es un observador y a su vez es observado por el símbolo A que es un observador. Un cambio en el símbolo C, notifica a su observador B, el cual es actualizado según la dependencia del mismo hacia C y luego notifica a su observador A y así sucesivamente hasta terminar con la cadena de dependencias, actualizando así la estructura y a su vez su representación gráfica.

32

DISEÑO E IMPLEMENTACIÓNDISEÑO E IMPLEMENTACIÓN

Figura 2.12 Árbol de representación del patrón Observer.

2.3.2 Patrón de diseño Singleton

El patrón Singleton (Kak 2014) se una para asegurase de que exista solo una instancia de una clase, dando un punto de acceso global para poder acceder a esta instancia, pero debe garantizar que exista un solo objeto de dicha clase.

La implementación del patrón Singleton en la clase TreeKconfig y Resource permite tener una sola instancia de las mismas y les hace un acceso global dentro del plugin, necesario por la gran utilidad de las mismas en el plugin. Su implementación se realizó como se describe en (Kak 2014).

2.4 Diagrama de casos de usos

Los diagramas de casos de usos se utilizan para especificar la comunicación y el comportamiento de un sistema mediante su interacción con los usuarios. Proporcionan un medio sistemático e intuitivo de capturar requisitos funcionales dirigiendo todo el proceso de desarrollo debido a que la mayoría de las actividades como el análisis, diseño y prueba se llevan a cabo partiendo de los casos de uso.

Según (Stephens 2015) los diagramas de casos de uso son una secuencia de acciones, incluyendo variantes, que el sistema puede llevar a cabo, y que producen un resultado observable de valor para un actor concreto.

33

DISEÑO E IMPLEMENTACIÓNDISEÑO E IMPLEMENTACIÓN

A continuación, en la Figura 2.13, se muestra el diagrama de casos de uso y actores de la aplicación.

Figura 2.13 Diagrama de casos de usos.

El plugin implementado está destinado para que los desarrolladores sean capaces de llevar a cabo cada uno de los casos de uso descritos anteriormente. A continuación, se exponen características específicas de cada caso de uso.

Tabla 2.1 Gestionar compilación.

Caso de uso Gestionar compilación Actor Desarrollador Resumen El desarrollador puede crear nuevos directorios de compilación o modificar los existentes, estas acciones incluyen la configuración de las opciones de compilación. Estos directorios son creados en el directorio fiasco/src/build del código fuente del propio microkernel. Además los directorios de compilación pueden ser eliminados. Precondiciones

34

DISEÑO E IMPLEMENTACIÓNDISEÑO E IMPLEMENTACIÓN

Tabla 2.2 Reiniciar directorios de compilación.

Caso de uso Reiniciar directorios de compilación Actor Desarrollador Resumen El desarrollador puede luego de haber compilado el microkernel limpiar el directorio donde se efectuó la compilación. Esta acción elimina un conjunto de ficheros creados por el propio sistema de compilación del microkernel. Precondiciones

Tabla 2.3 Compilar el microkernel Fiasco.OC.

Caso de uso Compilar el microkernel FiascoOC Actor Desarrollador Resumen El desarrollador puede compilar el microkernel FiascoOC. Precondiciones Crear un directorio de compilación y configurar las opciones de compilación o seleccionar uno existente y configurado.

2.5 Diagrama de actividades

Los diagramas de actividades describen el comportamiento dinámico de un sistema, haciendo hincapié en la secuencia de actividades que se tienen que realizar y las condiciones que guardan o disparan esas actividades. De acuerdo a (Stephens 2015) el diagrama de actividad gráficamente, es una colección de nodos y arcos que se utilizan para el modelado de los aspectos dinámicos de los sistemas y es fundamentalmente un diagrama que muestra el flujo de control entre actividades.

35

DISEÑO E IMPLEMENTACIÓNDISEÑO E IMPLEMENTACIÓN

A continuación, en la Figura 2.14, se muestra el diagrama de actividades para el caso de uno compilar el microkernel FiascoOC.

Figura 2.14 Diagrama de actividades para el caso de uso gestionar compilación.

2.6 Diagrama de clases

Los diagramas de clases son diagramas de estructura estática que muestran las clases del sistema y sus interrelaciones, incluyendo herencia, agregación, asociación entre otros. Según lo planteado en (Stephens 2015) los diagramas de clases son el esquema más común encontrado en los sistemas de modelado orientados a objetos. Un diagrama de clases

36

DISEÑO E IMPLEMENTACIÓNDISEÑO E IMPLEMENTACIÓN muestra un conjunto de clases, interfaces y colaboraciones y sus relaciones. En la Figura 2.15 se muestra el diagrama de clases del plugin.

37

DISEÑO E IMPLEMENTACIÓNDISEÑO E IMPLEMENTACIÓN

Figura 2.15 Diagrama de clases del plugin.

38

DISEÑO E IMPLEMENTACIÓNDISEÑO E IMPLEMENTACIÓN

2.7 Diagrama de paquetes

Muestra como un sistema está dividido en agrupaciones lógicas mostrando las dependencias entre esas agrupaciones. Dado que normalmente un paquete está pensado como un directorio, los diagramas de paquetes suministran una descomposición de la jerarquía lógica de un sistema.

Según lo planteado en (Stephens 2015) visualizar, especificar, construir y documentar los grandes sistemas implica la manipulación potencialmente un gran número de clases, interfaces, componentes, nodos, diagramas y otros elementos. A medida que se escala hasta sistemas de este tipo, será necesario organizar estos elementos. En el UML, el paquete es un mecanismo de propósito general para la organización de los elementos de modelado en grupos. En la Figura 2.16 se muestra el diagrama de paquetes del plugin.

Figura 2.16 Diagrama de paquetes del plugin.

En la Tabla 2.4 se describen los paquetes existentes en el plugin.

Tabla 2.4 Descripción de los paquetes.

Paquete Descripción uclv.xetid.attribute Contiene las clases que representan los atributos de los elementos del lenguaje

39

DISEÑO E IMPLEMENTACIÓNDISEÑO E IMPLEMENTACIÓN

Kconfig. uclv.xetid.polaca Contiene la clase ArrayPolaca, que permite la representación de las expresiones lógicas y los métodos para su evaluación. uclv.xetid.symbol Contiene las clases que representan cada uno de los símbolos de acuerdo con su tipo y especificidades para cada uno de ellos. uclv.xetid.tree Contiene las clases implementan la estructura TreeKconfig y las que permiten a la estructura ser visualizada por un TreeView. uclv.xetid.grammar Contiene las clases generadas por ANTRL 4 para analizar los ficheros Kconfig a partir de la gramática Kconfig.g4 y las clases que nutren la estructura TreeConfig a partir del árbol sintáctico generado por ANTLR 4. uclv.xetid.gui Contiene las clases que manejan la interfaz visual del plugin. uclv.xetid.popup Contiene las clases que permiten el manejo de los menús para el plugin. uclv.xetid.fiasco Contiene las principales clases del plugin. Las cuales activan y manipulan los recursos del mismo.

40

DISEÑO E IMPLEMENTACIÓNDISEÑO E IMPLEMENTACIÓN

2.8 Descripción del plugin Fiasco.OC Compilator

El plugin para la configuración y compilación del microkernel FiascoOC permite la integración con el sistema de desarrollo integrado Eclipse, brindando a los desarrolladores facilidades de configuración y compilación desde el propio Eclipse. El mismo fue creado en la plataforma Eclipse versión 3.8.0 de la distribución Juno. En la Figura 2.17 se muestra el plugin integrado dentro de la plataforma de Eclipse.

Figura 2.17 Integración del plugin Fiasco.OC Compilator (Business & Corp 2006).

El mismo brinda las siguientes funcionalidades a los desarrolladores:

• Gestionar configuración de compilación.

• Compilar configuración de compilación.

• Modificar configuraciones de compilación existente.

• Activar/Desactivar configuración de compilación.

41

DISEÑO E IMPLEMENTACIÓNDISEÑO E IMPLEMENTACIÓN

2.9 Conclusiones del capítulo

En este capítulo se realizó un análisis de los diferentes requisitos funcionales que tiene el plugin propuesto. Los mismos fueron modelados a través del diagrama de casos de usos, donde se refleja su relación con los desarrolladores. También se hizo un análisis del diseño e implementación del plugin planteando su concepción general, apoyado en los diagramas de actividad, diagrama de clases y diagrama de paquetes.

Se implementó la gramática Kconfig.g4 (Ver en el anexo 1) para el análisis del lenguaje Kconfig. Con el uso de la herramienta para el reconocimiento de lenguajes ANTLR 4 y la gramática Kconfig.g4 se implementó la lógica del lenguaje Kconfig.

A través de las facilidades que brinda IDE Eclipse para su extensión se desarrolló el plugin que brinda a los desarrolladores facilidades para la configuración y compilación del microkernel Fiasco.OC.

42

CAPÍTULO 3. PREUBAS Y RESULTADOS

PRUEBAS Y RESULTADOSPRUEBAS Y RESULTADOS

3. PRUEBAS Y RESULTADOS En este capítulo se exponen las pruebas realizadas para la validación del plugin Fiasco.OC Compilator. Las mismas son divididas en tres etapas: la primera donde se valida el analizador sintáctico y la gramática Kconfig.g4 implementadas para el plugin. En la segunda la integración con el plugin Fiasco.OC Editor, pues este es el encargado de gestionar los proyectos de tipo Fiasco.OC que luego proceden a ser compilados; y por último, las pruebas de funcionamiento del plugin Fiasco.OC Compilator.

3.1 Pruebas para la validación de la gramática Kconfig.g4

Para validar el analizador sintáctico implementado para el lenguaje Kconfig se analizaron los ficheros Kconfig existentes en el código fuente del microkernel seL4 de la familia L4 y microkernel Fiasco.OC. En cada caso se validó la propuesta desarrollada comparando la lógica del lenguaje del plugin Fiasco.OC Compilator con las propias herramientas de cada uno de los .

3.1.1 Microkernel seL4

El microkernel seL4 de la familia L4 en su proceso de compilación también permite configurar las opciones de este proceso a través de ficheros descritos en el lenguaje Kconfig (Klein et al. 2009). Para validar la gramática Kconfig.g4 empleando los ficheros Kconfig de este microkernel se utilizaron dos configuraciones, para las arquitecturas ARM y x86 (Blem et al. 2013). En las Figura 3.1¡Error! No se encuentra el origen de la referencia. y Figura 3.2 se muestra los resultados obtenidos por el analizador sintáctico en una ventana, donde en ambos casos puede apreciarse la estructura jerárquica de este lenguaje donde cada nodo representa una opción a configurar para el proceso de compilación. En ambos casos puede apreciarse que las opciones que se encuentran activas son las deseadas y las obtenidas en caso de emplear las propias herramientas de este microkernel. Además, durante el proceso de análisis se realizaron cambios en varios parámetros de cada configuración, logrando como resultado en todos los casos la configuración correcta de todos los parámetros de acuerdo con las herramientas de ambos microkernels.

42

PRUEBAS Y RESULTADOSPRUEBAS Y RESULTADOS

Figura 3.1 Microkernel seL4. ARM activado.

Figura 3.2 Microkernel seL4. X86 activado.

43

PRUEBAS Y RESULTADOSPRUEBAS Y RESULTADOS

3.1.2 Microkernel Fiasco.OC

En las pruebas realizadas a los ficheros Kconfig del microkernel Fiasco.OC, se compararon además dos ficheros resultantes del proceso de configuración, globalconfig.out y globalconfig.h. En el fichero globalconfig.out todas las opciones activas (distintas de n y habilitadas) son escritas con el prefijo CONFIG_=, donde variable representa el nombre de la variable asociada a una opción y su valor correspondiente, las variables que toman valor ―n‖ durante el proceso de configuración se representan como: CONFIG_ is not set. Mientras que en el fichero globalconfig.h se definen de forma similar de acuerdo a la estructura siguiente #define CONFIG_ donde variable representa el nombre de la opción y en este caso toma valor ―1‖ en la mayoría de los casos, aunque puede tomar otros en algunos casos. En el microkernel seL4 no se realizaron estas pruebas, porque el proceso de compilación no es el mismo que el de Fiasco.OC.

En la Figura 3.3 se pueden apreciar los resultados obtenidos, a la izquierda la herramienta implementada para el plugin, mientras que a la derecha la herramienta menuconfig del microkernel Fiasco.OC para la configuración IA-32, como puede apreciarse existe correspondencia en las opciones empleando ambas herramientas.

Figura 3.3 Comparando plugin con menuconfig.

En las Figura 3.4 y Figura 3.5 se muestran los globalconfig.out y globalconfig.h obtenidos a partir del proceso de configuración anterior (Ver Figura 3.3), de izquierda a derecha, el

44

PRUEBAS Y RESULTADOSPRUEBAS Y RESULTADOS fichero generado por el plugin y el generado por del microkernel Fiasco.OC respectivamente. En ambas figuras puede apreciarse que a pesar de no ser generadas en el mismo orden las opciones, cosa que no afecta el proceso de compilación de Fiasco.OC, los valores para cada opción configurada coinciden en todos los casos.

Figura 3.4 Comparando los globalconfig.out.

Figura 3.5 Comparando los globalconfig.h

45

PRUEBAS Y RESULTADOSPRUEBAS Y RESULTADOS

3.2 Pruebas de integración con el plugin Fiasco.OC Editor.

El plugin Fiasco.OC Compilator depende del plugin Fiasco.OC Editor, pues este último es el encargado de gestionar la creación de proyectos de tipo Fiasco.OC. Para realizar la prueba de integración primeramente se procedió a crear un proyecto de tipo Fiasco.OC empleando el plugin antes mencionado (Ver Figura 3.6). Posteriormente, una vez creado el proyecto se activa el plugin Fiasco.OC Compilator brindando las opciones a los desarrolladores para configurar su proceso de compilación.

En la Figura 3.6 se puede apreciar un proyecto de tipo Fiasco.OC creado a través del plugin Fiasco.OC Editor y a su vez las opciones brindadas por el plugin Fiasco.OC Compilator, recogidas en el menú Fiasco.OC microkernel .

Figura 3.6 Proyecto Fiasco.OC creado en Eclipse.

En la figura anterior se puede apreciar que el proyecto creado previamente fue definido para la arquitectura ARM, por lo que solo son indexados los ficheros del código fuente que tienen información para esta arquitectura. Por otro lado, para probar la integración del plugin con las opciones de configuración se procedió a cambiar la configuración para la arquitectura x86 (ia32); el resultado de este proceso puede apreciarse en la Figura 3.7.

46

PRUEBAS Y RESULTADOSPRUEBAS Y RESULTADOS

Figura 3.7 Proyecto Fiasco.OC para ia32.

Los resultados obtenidos muestran que la integración de ambos plugin funciona de forma correcta.

3.3 Pruebas de funcionamiento del plugin Fiasco.OC Compilator.

El plugin Fiasco.OC Compilator puede ser accedido al realizar clic secundario sobre un proyecto FiascoOC, este despliega un menú contextual que contiene la opción Fiasco.OC microkernel como se muestra en la Figura 3.8, el cual a su vez despliega otro menú contextual que contiene las funcionalidades del plugin:

 Build active configuration: compila el microkernel Fiasco.OC para la configuración activa.  Build All configuration: compila el microkernel Fiasco.OC para todas las configuraciones definidas.  Manage build configuration: permite gestionar las configuraciones definidas por el usuario para la compilación o selección de configuraciones existentes.  Configure active configuration: permite cambiar las opciones para la compilación de la configuración activa.  Clean: elimina los archivos generados en el proceso de compilación de la configuración activa.

47

PRUEBAS Y RESULTADOSPRUEBAS Y RESULTADOS

Figura 3.8 Funcionalidades del plugin Fiasco.OC Compilator.

A continuación, se describen las principales interfaces del plugin Fiasco.OC Compilator con un conjunto de pruebas de funcionamiento que le fueron aplicadas. En la Figura 3.9 se muestra la ventana que se lanza al seleccionar la opción Manage Build Configuration, en la misma puede apreciarse que se listan todas las configuraciones de compilación definidas por el usuario. Además, el usuario puede realizar las operaciones de adición, eliminación y activación de una configuración, empleando los botones Add, Remove y Set Active que se encuentran en la ventana antes mencionada.

Figura 3.9 Gestionar configuraciones de compilación.

En la figura anterior puede observarse que se definieron tres nuevas configuraciones de compilación para tres arquitecturas diferentes: ia32, arm y amd, además en el proyecto se

48

PRUEBAS Y RESULTADOSPRUEBAS Y RESULTADOS encuentra activa la configuración para ia32, que en imágenes anteriores se muestra como esta configuración es enlazada con las opciones del plugin Fiasco.OC Editor.

Como resultado de este proceso de configuración se muestra en la Figura 3.10 el contenido del directorio build del código fuente del proyecto, que como puede apreciarse se encuentran definidos los tres directorios asociados a las configuraciones previamente realizadas.

Figura 3.10 Directorio build.

Además, si nos adentramos dentro del directorio de la configuración activa (ia32) podemos observar en la Figura 3.11 que el contenido del directorio es el que necesitan las herramientas del proceso de construcción de Fiasco.OC, los Makefiles y los archivos de configuraciones Kconfig, globalconfig.out y globalconfig.h.

Figura 3.11 Directorio de compilación ia32.

3.3.1 Compilando el microkernel Fiasco.OC

Para compilar el código fuente del microkernel Fiasco.OC a través del plugin Fiasco.OC Compilator es necesario primeramente crear un proyecto de tipo Fiasco.OC se realiza clic secundario y se busca la opción ―Fiasco.OC microkernel” y desplegamos el submenú de

49

PRUEBAS Y RESULTADOSPRUEBAS Y RESULTADOS esta opción y se realiza clic en la opción ―Build active configuration‖ como se aprecia en la Figura 3.12.

Figura 3.12 Funcionalidades del plugin.

Como su nombre lo indica esta opción compila la configuración que se encuentra activa en ese momento, es por ello que primero debe chequearse si realmente está activa la configuración que se desea compilar.

Para probar esta funcionalidad se compilo el microkernel Fiasco.OC para las arquitecturas ia32 y arm. El proceso de compilación de Fiasco.OC comienza procesando todos los ficheros escritos en su dialecto de preprocesamiento y posteriormente comienza a compilar todos los ficheros resultantes del proceso anterior. Este proceso de compilación se ejecuta de acuerdo con las opciones configuradas en los ficheros globalconfig.out y globalconfig.h resultantes del proceso de configuración. El resultado del proceso de compilación de Fiasco.OC se centra en la confección de una imagen binaria que adquiere una estructura determinada de acuerdo con la arquitectura a la que se desea compilar, esta imagen se genera bajo el nombre fiasco.image.

Como se mencionó anteriormente se compilo a Fiasco.OC para las arquitecturas ia32 y arm empleando las opciones implementadas en el plugin. En ambos casos se obtuvieron las imágenes binarias correspondientes. Para comprobar que estas son las mismas que las generadas a partir de las herramientas se utilizó la imagen generada por el plugin en el

50

PRUEBAS Y RESULTADOSPRUEBAS Y RESULTADOS sistema de trabajo del framework L4Re para probar dos de sus ejemplos básicos: hello y cltnsrv, en el primero se chequea las funcionalidades básicas del framework, mientras que en el segundo recrea un escenario de cliente-servidor que se encarga de probar las API del sistema. En ambos casos los resultados fueron satisfactorios.

3.4 Conclusiones del Capítulo En este capítulo se realizaron varias pruebas al plugin implementado. Estas fueron aplicadas a diferentes partes del mismo, por un lado a la gramática implementada para el analizador sintáctico del lenguaje Kconfig; estas fueron realizadas en los microkernel Fiasco.OC y seL4 de la familia L4. Además se aplicaron pruebas de integración y funcionamiento al plugin implementado Fiasco.OC Compilator.

51

CONCLUSIONES

CONCLUSIONES En el desarrollo de la presente investigación se logró identificar el proceso de compilación del microkernel Fiasco.OC, así como sus herramientas y principales dependencias. Para el mismo fue necesaria la implementación de un analizador sintáctico para el lenguaje Kconfig, en el cual se describen las opciones de compilación. Se diseñó e implementó la estructura de datos TreeConfig en la cual se almacenan las opciones de compilación e implementa la lógica del lenguaje Kconfig permitiéndole a los desarrolladores configurar las opciones de compilación de acuerdo a sus necesidades.

Se diseñó e implementó el plugin Fiasco.OC Compilator en la plataforma Eclipse, capaz de permitir a los desarrolladores automatizar el proceso de compilación del microkernel Fiasco.OC. El mismo gestiona la configuración de compilación lo cual incluye la creación de nuevos directorios de compilación y su configuración, además de compilar una configuración, modificar configuraciones de compilación existentes y activar/desactivar configuraciones de compilación.

El plugin Fiasco.OC Compilator se evaluó a través de pruebas de integración y funcionamiento. El plugin se activa en los proyectos de tipo Fiasco.OC, para lo cual se debe tener corriendo el plugin Fiasco.OC Editor, pues este permite gestionar los proyectos de tipo Fiasco.OC. El plugin ofrece resultados iguales a las herramientas de compilación del propio microkernel Fiasco.OC.

RECOMENDACIONES

RECOMENDACIONESRECOMENDACIONES

RECOMENDACIONES Para futuros trabajos de recomienda:

• Profundizar en la estructura TreeConfig para mejorar la implementación lógica del lenguaje Kconfig.

• Integrar el proceso de compilación con las interfaces del CDT de Eclipse.

• Crear una herramienta para emplear la gramática implementada en otros proyectos como Linux, seL4, entre otros.

55

REFERENCIAS BIBLIOGRAFICAS

REFERENCIAS BIBLIOGRAFICASREFERENCIAS BIBLIOGRAFICAS

REFERENCIAS BIBLIOGRAFICAS

Alexander, C., Ishikawa, S. & Silverstein, M., 1977. Pattern languages. Center for Environmental Structure, 2, p.1977. Blem, E., Menon, J. & Sankaralingam, K., 2013. A Detailed Analysis of Contemporary ARM and x86 Architectures, Business, I. & Corp, M., 2006. Eclipse Platform Technical Overview. CDT, A.P.I., 2015. CDT Parsing Overview. (En: \url{http://wiki.eclipse.org/CDT)}, 2. Available at: http://wiki.eclipse.org/CDT/designs/Overview_of_Parsing. Eclipse, A.P.I., 2015. Platform architecture. (En: \url{http://help.eclipse.org/}), 2. Available at: http://help.eclipse.org/neon/index.jsp?topic=/org.eclipse.platform.doc. El-sharkawy, S. et al., 2015. Analysing the Kconfig Semantics and Its Analysis Tools. , pp.45–54. Feske, N., 2015. Genode Framework. (En \url{http://genode.org/files/53bcb8e33fe6602fed25edc3c7b922c5/manual-2015-04- 27.pdf}). Genode/Labs, 2016. Genode - Genode components overview. Available at: https://genode.org.documentation/. Informatik-berichte, H., El-sharkawy, S. & Asad, N., 2015. Analysing the KConfig Semantics and Related Analysis Tools. , (1). Kak, A.C., 2014. Designing with Objects: Object-oriented Design Patterns Explained with Stories from Harry Potter, John Wiley & Sons. Klein, G. et al., 2009. seL4: Formal verification of an OS kernel. Proceedings of the ACM SIGOPS 22nd Symposium on Operating System Principles, pp.207–220. Available at: http://dl.acm.org/citation.cfm?id=1629596. Liedtke, J., 1995. On μ-kernel construction. In 15th ACM Symposium on Operating System Principles (SOSP). pp. 237–250. Love, R., 2010. Linux Kernel Development 3ed ed., Addison-Wesley. Makhorin, A., 2011. CNF Satisfiability Problem. , (August), pp.1–6. Martin, R.C., 2003. Agile software development: principles, patterns, and practices, Prentice Hall PTR.

56

REFERENCIAS BIBLIOGRAFICASREFERENCIAS BIBLIOGRAFICAS

NG, M.S.S.H.S. & Mihalkovic, L., 2005. SWT/JFace in Action, Manning Publications Co. Available at: http://read.pudn.com/downloads165/ebook/754950/SWT{_}JFace. Parr, T., 2013. The Definitive ANTLR 4 Reference Intergovernmental Panel on Climate Change, ed., Cambridge: Cambridge University Press. Available at: http://ebooks.cambridge.org/ref/id/CBO9781107415324A009. Parr, T., Harwell, S. & Fisher, K., 2014. Adaptive LL(*) parsing. Proceedings of the 2014 ACM International Conference on Object Oriented Programming Systems Languages & Applications - OOPSLA ’14, (November), pp.579–598. Available at: http://dl.acm.org/citation.cfm?doid=2660193.2660202. Roch, B., 2004. Monolithic kernel vs. Microkernel. (En: \url{http://www.vmars.tuwien.ac.at/courses/akti12/journal/04ss/article_04ss_Roch.pdf }). Available at: http://www.vmars.tuwien.ac.at/courses/akti12/journal/04ss/article_04ss_Roch.pdf. SILBERSCHATZ, A., GALVIN, P.B. & GAGNE, G., 2013. Operating System Concepts, Silva, V., 2009. Practical eclipse rich client platform projects, Stephens, R., 2015. Beginning Software Engineering, John Wiley & Sons. Available at: http://booksupport.wiley.com. Tanenbaum, A.S., 2009. Sistema Operativos Modernos, Available at: http://www.springerlink.com/index/10.1007/1-4020-0613-6_2346. TU-DresdenOSGroup, 2015. L4Re - L4 Runtime Environment. (En: \url{http://os.inf.tu- dresden.de/l4re}).

57

ANEXOS

ANEXOS

ANEXOS

grammar Kconfig; tokens { INDENT, DEDENT }

@parser::members {

public boolean flags_default_choice=false;

public boolean flags_select=false;

public boolean flags_range=false; /*No machea los atributos select y range si el tipo no lo permite*/

public boolean bit_type=true;

public boolean bit_prompt=true;

public boolean bit_help=true; /*Permite que un simbolo tenga un solo atributo de estos tipos*/

public boolean cancel_type=true; /*Cancela los tipos STRING INT HEX (falso)

para menu pues solo permite tipos tristate o bool*/

}

@lexer::members {

// A queue where extra tokens are pushed on drarocha(see the NEWLINE lexer rule). private java.util.LinkedList tokens = new java.util.LinkedList<>();

58

ANEXOS

// Indentation level.

int indents=0;

public boolean flags_eol = true; /*Permite machear el fin de linea por T_EOL(true) o NEWLINE(false)*/

public boolean flags_help=false; /*Permite machear el token T_TEXTHELP(true)*/

// The most recently produced token.

private Token lastToken = null;

@Override

public void emit(Token t) {

super.setToken(t);

tokens.offer(t);

}

@Override

public Token nextToken() {

// Check if the end-of-file is ahead and there are still some DEDENTS expected.

if ( _input.LA(1) == EOF && indents!=0 ){

// Remove any trailing EOF tokens from our buffer.

for (int i = tokens.size() - 1; i >= 0; i--) {

if (tokens.get(i).getType() == EOF) {

tokens.remove(i);

}

}

59

ANEXOS

// First emit an extra line break that serves as the end of the statement.

this.emit(commonToken(KconfigParser.NEWLINE, "\n"));

// Now emit as much DEDENT tokens as needed.

if (indents != 0) {

this.emit(createDedent());

indents=0;

}

// Put the EOF back on the token stream.

this.emit(commonToken(KconfigParser.EOF, ""));

}

Token next = super.nextToken();

if (next.getChannel() == Token.DEFAULT_CHANNEL) {

// Keep track of the last token on the default channel.

this.lastToken = next;

}

return tokens.isEmpty() ? next : tokens.poll();

}

60

ANEXOS

private Token createDedent() {

CommonToken dedent = commonToken(KconfigParser.DEDENT, "");

dedent.setLine(this.lastToken.getLine());

return dedent;

}

private CommonToken commonToken(int type, String text) {

int stop = this.getCharIndex() - 1;

int start = text.isEmpty() ? stop : stop - text.length() + 1;

return new CommonToken(this._tokenFactorySourcePair, type, DEFAULT_TOKEN_CHANNEL, start, stop);

}

// Calculates the indentation of the provided spaces, taking the

// following rules into account:

//

// "Tabs are replaced (from left to right) by one to eight spaces

// such that the total number of characters up to and including

// the replacement is a multiple of eight [...]"

//

static int getIndentationCount(String spaces) {

int count = 0;

61

ANEXOS

for (char ch : spaces.toCharArray()) {

switch (ch) {

case '\t':

count += 8 - (count % 8);

break;

default:

// A normal space char.

count++;

}

}

return count;

}

}

/*

* parser rules

*/ input: T_EOL+ start

| start

; start: mainmenu_stmt stmt_list

| stmt_list

62

ANEXOS

| EOF

; stmt_list: stmt_list common_stmt

| stmt_list choice_stmt

| stmt_list menu_stmt

| common_stmt

| choice_stmt

| menu_stmt

; common_stmt: if_stmt

| config_stmt

| source_stmt

| comment_stmt

; config_stmt: config_start att_symbol T_EOL?

{

bit_type=true;

bit_prompt=true;

bit_help=true;

flags_select=false;

flags_range=false;

63

ANEXOS

}

; config_start: (T_CONFIG | T_MENUCONFIG) T_NAME T_EOL+

; att_symbol: att_symbol att_type

| att_symbol att_prompt

| att_symbol att_default

| att_symbol att_depends

| att_symbol att_help

| att_symbol att_select

| att_symbol att_range

| att_symbol att_options

| att_symbol T_EOL

| att_type

| att_prompt

| att_default

| att_depends

| att_help

| att_select

| att_range

| att_options

64

ANEXOS

; att_type: {bit_type}? (type_general

| def_tristate

| def_bool)

{

bit_type=false;

}

; type_general: type prompt_opt? T_EOL

;

/*Esta notacion es para un tipo mas un valor

"def_bool/"def_tristate" ["if" ]*/ def_bool: T_DEFBOOl expr_stmt if_expr? T_EOL

; def_tristate: T_DEFTRISTATE expr_stmt if_expr? T_EOL

; att_prompt: {bit_prompt}? T_PROMPT prompt if_expr? T_EOL

{

bit_prompt=false;

}

;

65

ANEXOS

att_choice_default: {flags_default_choice}? T_DEFAULT T_NAME if_expr? T_EOL

; att_default: {!flags_default_choice}? T_DEFAULT expr_stmt if_expr? T_EOL

; att_depends: T_DEPENDS expr_stmt T_EOL

; att_select: {flags_select}? T_SELECT T_NAME if_expr? T_EOL

; att_range: {flags_range}? T_RANGE symbol symbol if_expr? T_EOL

; att_options: T_OPTION list_option option_arg? T_EOL

; option_arg: T_EQUAL prompt

; list_option: T_ENV

;

66

ANEXOS att_help: {bit_help}? T_HELP suite

{

bit_help=false;

}

; suite: NEWLINE INDENT text_help+ DEDENT

; text_help: T_TEXTHELP NEWLINE

; att_visible: T_VISIBLE expr_stmt T_EOL

; type: type_tristate

| type_bool

| type_string

| type_int

| type_hex

; type_tristate: T_TYPETRISTATE

{

flags_select=true;

};

67

ANEXOS

type_bool: T_TYPEBOOL

{

flags_select=true;

}

; type_string: {cancel_type}? T_TYPESTRING

; type_int: {cancel_type}? T_TYPEINT

{

flags_range=true;

}

; type_hex: {cancel_type}? T_TYPEHEX

{

flags_range=true;

}

; if_expr: T_IF expr_stmt

;

68

ANEXOS

/* choice entry */

/* que hay con el T_NAME */ choice: T_CHOICE T_NAME? T_EOL

{

cancel_type=false;

flags_default_choice=true;

}

; choice_entry: choice att_choice? T_EOL?

{

bit_help=true;

}

; choice_end: end

; choice_stmt: choice_entry choice_block choice_end T_EOL?

{

bit_type=true;

bit_prompt=true;

cancel_type=true;

flags_default_choice=false;

69

ANEXOS

}

;

/* Solo puede ser del tipo bool o tristate si es bool solo se

* puede seleccionar un symbol mientras que si es tristate varios symbol m

* T_OPTION T_EOL falta ver

*/ att_choice: att_choice att_type

| att_choice att_prompt

| att_choice att_choice_default

| att_choice att_depends

| att_choice att_help

| att_choice T_EOL

| att_type

| att_prompt

| att_choice_default

| att_depends

| att_help

; choice_block: choice_block common_stmt

| common_stmt

;

70

ANEXOS

/* if entry*/ if_entry: T_IF expr_stmt T_EOL

; if_end: end

; if_stmt: if_entry if_block? if_end T_EOL?

; if_block: if_block common_stmt

| if_block menu_stmt

| if_block choice_stmt

| common_stmt

| menu_stmt

| choice_stmt

; mainmenu_stmt: T_MAINMENU prompt T_EOL

;

/* menu entry */ menu: T_MENU prompt T_EOL

; menu_entry: menu att_menu?

;

71

ANEXOS

att_menu: att_visible

| list_depends

; list_depends: list_depends att_depends

| list_depends T_EOL

| att_depends

; menu_end: end

; menu_stmt: menu_entry menu_block menu_end T_EOL?

; menu_block: menu_block common_stmt

| menu_block menu_stmt

| menu_block choice_stmt

| common_stmt

| menu_stmt

| choice_stmt

; end: ( T_ENDCHOICE T_EOL | T_ENDIF T_EOL | T_ENDMENU T_EOL )

;

72

ANEXOS

source_stmt: T_SOURCE prompt T_EOL

; comment: T_COMMEN prompt T_EOL

; comment_stmt: comment list_depends?

; prompt_opt: prompt if_expr?

; expr_stmt: expr

; expr: symbol #SYMBOL

| symbol T_EQUAL symbol #equalSYMBOL

| symbol T_UNEQUAL symbol #unequalSYMBOL

| T_NOT expr #notEXPR

| expr T_OR expr #orEXPR

| expr T_AND expr #andEXPR

| T_PARENT_OPEN expr T_PARENT_CLOSE #parentEXPR

;

73

ANEXOS symbol: T_BOOL #symbolBOOL

| T_TRISTATE #symbolTRISTATE

| T_INTEGER #symbolINTEGER

| T_HEX_INTEGER #symbolHEX

| prompt #symbolPROMPT /*String*/

; prompt: T_NAME

| T_WORD_QUOTE

| T_WORD

;

/*

* lexer rules

*/

T_MAINMENU: 'mainmenu';

T_IF: 'if';

T_CHOICE: 'choice';

T_MENU: 'menu';

T_ENDCHOICE: 'endchoice';

T_ENDMENU: 'endmenu';

T_ENDIF: 'endif';

T_SOURCE: 'source';

74

ANEXOS

T_COMMEN: 'commen';

T_CONFIG: 'config';

T_MENUCONFIG: 'menuconfig';

T_DEFAULT: 'default';

T_PROMPT: 'prompt';

T_DEPENDS: 'depends on';

T_SELECT: 'select';

T_VISIBLE: 'visible if';

T_RANGE: 'range';

T_OPTION: 'option';

T_ENV: 'env';

T_DEFTRISTATE: 'def_tristate';

T_DEFBOOl: 'def_bool';

T_TYPETRISTATE: 'tristate';

T_TYPEBOOL: 'bool';

T_TYPESTRING: 'string';

T_TYPEINT: 'int';

T_TYPEHEX: 'hex';

75

ANEXOS

T_HELP: ('help'| '--help--') SPACES?

{

flags_eol=false;

flags_help=true;

}

;

T_AND: '&&' ;

T_OR: '||' ;

T_NOT: '!' ;

T_EQUAL: '=' ;

T_UNEQUAL: '!=' ;

T_PARENT_OPEN: '(' ;

T_PARENT_CLOSE: ')' ;

T_EOL: (( '\r'? '\n' | '\r' ) SPACES?)+ { flags_eol }?;

NEWLINE: ( '\r'? '\n' | '\r' ) SPACES?

{

String newLine = getText().replaceAll("[^\r\n]+", "");

String spaces = getText().replaceAll("[\r\n]+", "");

int next = _input.LA(1);

76

ANEXOS

if ( next == '\r' || next == '\n' || next == '#') {

// If we're inside a list or on a blank line, ignore all indents,

// dedents and line breaks.

skip();

}else{

emit(commonToken(NEWLINE, newLine));

int indent = getIndentationCount(spaces);

int previous = indents;

if (previous==0) {

indents=indent;

emit(commonToken(KconfigParser.INDENT, spaces));

}

else if (indent >= previous) {

// skip indents of the same size as the present indent-size

skip();

}

else {

this.emit(createDedent());

indents=0;

flags_eol=true;

77

ANEXOS

flags_help=false;

}

}

}

;

COMMENT: '#' ~[\r\n]* ->skip;

T_TEXTHELP: ~[\r\n]+ {flags_help}?;

SPACES: [ \t]+ ->skip;

ESCAPE: '\\\n' ->skip;

T_BOOL: ('n' | 'y');

T_TRISTATE: ('n' | 'y' | 'm');

T_INTEGER: (NON_ZERO_DIGIT DIGIT* | '0'+) ;

T_HEX_INTEGER: '0' [xX] HEX_DIGIT+;

T_NAME: ID_START ID_CONTINUE*;

T_WORD: '"' ~[\r\n]* '"';

T_WORD_QUOTE: '\'' ~[\r\n]* '\'' ;

/*T_WORD_SIMPLE: ~[\r\n]*;

*/

78

ANEXOS

/*

* fragments

*/

fragment NON_ZERO_DIGIT

: [1-9]

;

fragment DIGIT

: [0-9]

;

fragment HEX_DIGIT

: [0-9a-fA-F]

;

fragment ID_START

: '_'

| [A-Z]

| [a-z]

; fragment ID_CONTINUE

: ID_START

| [0-9]

;

79