2011-03-02 9 views
14

Estoy desarrollando un dispositivo basado en Linux utilizando un alix 2d13.Firmware basado en Linux, ¿cómo implementar una buena forma de actualizar?

He desarrollado un script que se encarga de crear un archivo de imagen, crear las particiones, instalar el gestor de arranque (syslinux), el kernel y el initrd y que se encarga de poner los archivos del sistema de archivos raíz en la partición correcta .

Los archivos de configuración se encuentran en el sistema de archivos tmpfs y se crean al iniciar el sistema mediante un software que lee un archivo XML que reside en una partición propia.

estoy buscando una manera de actualizar el sistema de archivos y he considerado dos soluciones:

  • la actualización del firmware es un archivo comprimido que podrían contener kernel, initrd y/o la partición rootfs, en este De esta forma, al reiniciar, initrd se ocupará de dd la imagen rootfs en la partición correcta;
  • la actualización del firmware es un archivo comprimido que podría contener dos archivos tar, uno para el arranque y otro para el sistema de archivos raíz.

Cada solución tiene sus propias ventajas: - una imagen de sistema de archivos me deja de eliminar archivos no utilizados, pero necesita una gran cantidad de tiempo y que matará a la memoria flash compacta rápidamente; - un archivo es más pequeño, necesita menos tiempo para la actualización, pero tendré el caos en el sistema de archivos raíz en poco tiempo.

Una solución alternativa podría ser poner una lista de archivos y colocar una secuencia de comandos de actualización previa/posterior en el archivo tar, para que cualquier archivo que no resida en la lista de archivos se elimine.

¿Qué opinas?

Respuesta

16

Utilicé el siguiente enfoque. Se basó en cierto modo en el documento "Creación de sistemas Linux integrados compatibles con Murphy", disponible en here. Usé las cosas de versiones.conf descritas en ese documento, no las de cfgsh.

  • Utilice un kernel de arranque cuya tarea es realizar un loop-back para montar el sistema de archivos raíz "principal". Si necesita un kernel más nuevo, ejecute kexec en ese kernel más nuevo inmediatamente después de montarlo en loop-back. Elegí poner el init completo del kernel de arranque en initramfs, junto con busybox y kexec (ambos vinculados estáticamente), y mi init fue un script de shell simple que escribí.
  • Uno o más sistemas de archivos raíz del "sistema operativo principal" existen en un sistema de archivos de "imagen del sistema operativo" como archivos de imagen de disco. El kernel de arranque elige uno de estos basado en un archivo versions.conf. Solo mantengo dos archivos de imagen principales del sistema operativo, el archivo actual y el posterior. Si falla el actual (más sobre la detección de fallas más adelante), el kernel de arranque inicia el repliegue. Si ambos fallan o no hay retroceso, el kernel de arranque proporciona un shell.
  • La configuración del sistema está en una partición separada. Esto normalmente no se actualiza, pero no hay ninguna razón por la que no podría ser.
  • Hay cuatro particiones totales: boot, OS image, config, y data. La partición de datos es para cosas de la aplicación del usuario que se destina a la escritura frecuente. el arranque nunca está montado de lectura/escritura. La imagen del sistema operativo solo se (vuelve a montar) de lectura/escritura durante las actualizaciones. config solo está montado de lectura/escritura cuando las cosas de configuración deben cambiar (ojalá nunca). los datos siempre están montados de lectura/escritura.
  • Los archivos de imagen de disco contienen un sistema Linux completo, incluyendo kernel, scripts de inicio, programas de usuario (por ejemplo, busybox, aplicaciones de productos) y una configuración predeterminada que se copia a la partición de configuración en el primer arranque. Los archivos son de cualquier tamaño que sea necesario para ajustar todo en ellos. Siempre y cuando deje espacio suficiente para que la partición de imagen del sistema operativo sea lo suficientemente grande como para caber tres archivos principales de imagen del sistema operativo (durante una actualización, no elimino el viejo repliegue hasta que se extraiga el nuevo), puedo permitir que la imagen del sistema operativo principal crezca según sea necesario. Estos archivos de imagen están siempre (en bucle) montados de solo lectura. El uso de estos archivos también elimina el dolor de lidiar con fallas en la actualización de archivos individuales dentro de un rootfs.
  • Las actualizaciones se realizan transfiriendo un tarball autoextraíble a un tmpfs. El comienzo de este script remonta la lectura/escritura de imagen del sistema operativo, luego extrae la nueva imagen del sistema operativo principal en el sistema de archivos de imagen del sistema operativo y luego actualiza el archivo versions.conf (utilizando el método de cambio de nombre descrito en el documento "murphy"). Una vez hecho esto, toco un archivo de sello que indica que ha ocurrido una actualización, luego reinicio.
  • El kernel de arranque busca este archivo de sello. Si lo encuentra, lo mueve a otro archivo de sello, luego inicia el nuevo archivo de imagen del sistema operativo principal. Se espera que el archivo de imagen del sistema operativo principal elimine el archivo de sello cuando se inicia correctamente. Si no lo hace, el perro guardián activará un reinicio, y luego el kernel de arranque lo verá y detectará una falla.
  • Observará que hay algunos posibles puntos de error durante una actualización: sincronización de versions.conf durante la actualización y tocar/eliminar los archivos de sello (tres instancias). No pude encontrar una manera de reducir estos más y lograr todo lo que quería. Si alguien tiene una mejor sugerencia, me encantaría escucharla. También podrían ocurrir errores en el sistema de archivos o fallas de energía al escribir la imagen del sistema operativo, pero espero que el sistema de archivos ext3 brinde algunas posibilidades de sobrevivir en ese caso.
+1

me gusta mucho tu solución, al final hice algo muy similar pero sin detección de falla de arranque, pero creo que implementaré algo similar: - reservaré un sector para la escritura de detección de falla de arranque usando operaciones directas de sincronización y sincronización - el kernel de arranque iniciará un initrd que informará un try-to-boot, con marca de tiempo y montará la imagen del sistema operativo - durante el proceso de arranque, el nuevo initrd informará, paso a paso con las marcas de tiempo, las fases de arranque para identificar los problemas - al final reportará en el sector de detección de fallas de arranque "todo listo" –

+0

Para la actualización prefiero descargar el tarball en la partición de datos y, en el reinicio, si el primer initrd detecta el tarball de actualización, manejará el tarball (puede ser seful agregar dos archivos especiales para identificar los archivos para eliminar y ejecutar un script de actualización). Después de la actualización, el primer initrd se aplicará al kernel nuevo, informando el arranque como actualización (para que el archivo tar se pueda eliminar). El tarball, por razones de seguridad, debe estar firmado con una clave privada. Para informar de errores podría utilizar el sector de disco anterior (detección de falla de arranque), solo tiene que hacer la escritura sincronizada para evitar problemas –

+0

Me gusta su idea de "sector de estado". Al menos mueve algunos de los puntos de falla a una sola ubicación de disco, y si ese sector falla, es posible que tenga sectores adicionales y podría intentar una recuperación, o al menos ofrecer un "modo de recuperación"." – Patrick

0

Puede formatear rápidamente las particiones antes de extraer los archivos tar. O vaya con la solución de imagen pero use la imagen más pequeña posible y después de hacer un cambio de tamaño del sistema de archivos (aunque eso no es necesario para el almacenamiento de solo lectura)

+0

mmm, si hago un dd realmente no necesito hacer un cambio de tamaño porque el sistema de archivos sabría su tamaño ... lo que realmente necesitaría es cambiar el tamaño de la partición en mbr. De todos modos, puedo evitar cambiar el tamaño haciendo una partición más grande (de hecho, necesito menos de 30 mb para que una partición de 64 mb esté bien). Iré por la solución tar + pre/post script de actualización + lista de archivos probablemente –

2

Puede tener una partición separada para la actualización (Say Side1/Side2). El kernel existente, rootfs está en Side1, luego coloca la actualización en Side2 y cambia. Con esto puede reducir la nivelación del desgaste y aumentar la vida útil, pero el dispositivo se vuelve más costoso.

Cuestiones relacionadas