¿Cómo crear un sistema Linux que ejecute una sola aplicación?

17

Estoy tratando de ejecutar una aplicación de Linux y todo lo que quiero ejecutar es esta aplicación fuera del arranque. Necesito redes y eso es todo (sin pantalla, periféricos, etc.). No quiero que se ejecuten otras aplicaciones para que la aplicación que ejecuto tenga el 100% de la CPU. es posible?

dschatz
fuente
No podrá tomar el 100% de la CPU ya que su sistema operativo todavía necesita algunos recursos.
n0pe
@MaxMackie Obviamente, pero me gustaría que el sistema operativo solo se haga cargo de la aplicación (por ejemplo, para fines de redes).
dschatz
1
Te das cuenta de que incluso con un entorno de escritorio cargado, pero sentado allí inactivo, no está usando ningún tiempo de CPU ¿verdad? Y el ram que está utilizando está sujeto a ser cambiado si otras aplicaciones lo demandan.
psusi
@dschatz Sería útil si incluyera más detalles en su pregunta. Como contarnos más sobre qué aplicación desea ejecutar, cómo desea que funcione y qué tipo de hardware está utilizando.
NN
Si es posible, me gustaría saber por qué quieres esto. Por lo que entiendo, desea eliminar todo del sistema operativo (consola incluida) solo para ejecutar su aplicación. Las ganancias de rendimiento serán marginales, entonces, ¿cuál es el punto de tener todo ese trabajo?
nmat

Respuestas:

13

Minimo initrd CPIO hello world programa paso a paso

ingrese la descripción de la imagen aquí

Compile un mundo hola sin ninguna dependencia que termine en un bucle infinito. init.S:

.global _start
_start:
    mov $1, %rax
    mov $1, %rdi
    mov $message, %rsi
    mov $message_len, %rdx
    syscall
    jmp .
    message: .ascii "FOOBAR FOOBAR FOOBAR FOOBAR FOOBAR FOOBAR FOOBAR\n"
    .equ message_len, . - message

No podemos usar sys_exit, o de lo contrario el kernel entra en pánico.

Luego:

mkdir d
as --64 -o init.o init.S
ld -o init d/init.o
cd d
find . | cpio -o -H newc | gzip > ../rootfs.cpio.gz
ROOTFS_PATH="$(pwd)/../rootfs.cpio.gz"

Esto crea un sistema de archivos con nuestro hello world en /init, que es el primer programa de usuario que ejecutará el kernel. También podríamos haber agregado más archivos d/y serían accesibles desde el /initprograma cuando se ejecute el núcleo.

Luego, cden el árbol del kernel de Linux, la compilación es la habitual y ejecútela en QEMU:

git clone git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
cd linux
git checkout v4.9
make mrproper
make defconfig
make -j"$(nproc)"
qemu-system-x86_64 -kernel arch/x86/boot/bzImage -initrd "$ROOTFS_PATH"

Y deberías ver una línea:

FOOBAR FOOBAR FOOBAR FOOBAR FOOBAR FOOBAR FOOBAR

en la pantalla del emulador! Tenga en cuenta que no es la última línea, por lo que debe buscar un poco más arriba.

También puede usar programas en C si los vincula estáticamente:

#include <stdio.h>
#include <unistd.h>

int main() {
    printf("FOOBAR FOOBAR FOOBAR FOOBAR FOOBAR FOOBAR FOOBAR\n");
    sleep(0xFFFFFFFF);
    return 0;
}

con:

gcc -static init.c -o init

Puede ejecutar en hardware real con un USB encendido /dev/sdXy:

make isoimage FDINITRD="$ROOTFS_PATH"
sudo dd if=arch/x86/boot/image.iso of=/dev/sdX

Gran fuente sobre este tema: http://landley.net/writing/rootfs-howto.html También explica cómo usar gen_initramfs_list.sh, que es un script del árbol de fuentes del kernel de Linux para ayudar a automatizar el proceso.

Siguiente paso: configure BusyBox para que pueda interactuar con el sistema: /unix/2692/what-is-the-smallest-possible-linux-implementation/203902#203902

Probado en Ubuntu 16.10, QEMU 2.6.1.

Ciro Santilli 新疆 改造 中心 法轮功 六四 事件
fuente
3

puede iniciar el kernel con el init=/path/to/myappparámetro definido en su gestor de arranque.

Michał Šrajer
fuente
2
Esta es una solución bastante extrema. Reemplazar el script de inicio con la aplicación del usuario hará que la aplicación se ejecute sin conexión en red, sin ningún sistema de archivos que no sea el rootfs montado (sin sysfs o proc o tmpfs), y posiblemente no se crearán algunos nodos de dispositivo.
aserrín
2
@sawdust: totalmente de acuerdo. Pero la pregunta también fue un poco extrema ... :-)
Michał Šrajer
2

Parece que estás tratando de configurar un quiosco . La mayoría de las guías en Internet se centran en un navegador web como Firefox como la única aplicación que se ejecuta. Eche un vistazo a esta guía para obtener ideas.

William Jackson
fuente
2
Hmm, realmente solo estoy tratando de ejecutar una sola aplicación con redes. No quiero que se ejecute ninguna X y la menor cantidad posible de otras aplicaciones. No veo cómo esto restringe la ejecución de todos los demonios innecesarios.
dschatz
¿Puede la aplicación ejecutarse sin X?
Journeyman Geek
2

Ciertamente, puede ejecutar una sola aplicación de usuario después de iniciar el núcleo. Pero no tendrá el 100% de la CPU porque habrá otros procesos relacionados con el núcleo que deben existir. Esto se hace comúnmente en dispositivos Linux integrados, por ejemplo, enrutadores inalámbricos. También tengo experiencia de primera mano haciendo esto para una aplicación multiproceso.

Una vez que el kernel se ha iniciado, se ejecuta un script de inicialización o inicio. Lea sobre los niveles de ejecución de Linux y el proceso de inicio. Hay varios esquemas de inicio en uso, por lo que no es posible ser específico. Pero Linux le permitirá configurar exactamente qué aplicaciones y demonios se ejecutarán para su situación. Además de un archivo de inicio en la raíz, los archivos que deben modificarse están en / etc , y en particular /etc/init.d

Por cierto, a menos que sea un superprogramador o antes de ejecutar un servidor GDB remoto, necesitará algún tipo de consola de depuración (ya sea la consola de la PC o un puerto serie) para su aplicación. Esto le permitirá ser notificado de fallas seg, errores de bus y fallas de aserción. Así que planea tener algo de "periférico" además de "redes".

serrín
fuente
1

Hay algunas aplicaciones del sistema que deben ejecutarse, además de ellas, seguro, puede dedicar el resto de los recursos de la computadora a esa aplicación. Para tener el mínimo, puede echar un vistazo a distribuciones de Linux realmente pequeñas como TinyCore Linux, etc.

También dependería de la aplicación misma, qué servicios requiere además de la red, etc.

Creo que si puede proporcionar información más específica, obtendrá una respuesta más detallada.

Como qué tipo de aplicación, etc.

bakytn
fuente
Mi aplicación utiliza la biblioteca pthread para ejecutar una carga de trabajo multiproceso (operaciones aritméticas) y puede recibir instrucciones para hacer diferentes cálculos basados ​​en la entrada de tcp / ip. En cuanto a TinyCore Linux, arranca en un entorno de escritorio completo, que no quiero.
dschatz
TinyCore tiene un hermano menor llamado MicroCore. Sin GUI, échale un vistazo.
n0pe
1
@MaxMackie Realmente no quiero ninguna interfaz en la máquina fuera de la pila tcp / ip. La aplicación puede bloquear en un puerto y puede controlarse a través de paquetes tcp enviados a ese puerto.
dschatz
1
Recomiendo un entorno con pocos servicios en ejecución ( mira esto linuxhelp.blogspot.com/2006/04/… ) y casi nada más que tu aplicación y sus dependencias instaladas.
n0pe
1
@dschatz bueno, entonces necesitas hackear el kernel, eliminar todo lo demás y compilar tu aplicación en él. no bash no hay nada más. solo tu aplicación ... jaja.
bakytn
1

Si realmente no quiere nada más que el kernel de Linux, las redes y su aplicación, la única forma de hacerlo es esta:

  • Tendrá que hacer que su aplicación sea un módulo del núcleo: asegúrese de que esté depurada y bien probada. Este módulo del núcleo tendría que inicializar las cosas que normalmente se hacen a través del espacio de usuario, como establecer las direcciones IP de la interfaz y todo lo bueno.
  • Deberá descargar y configurar ( make menuconfig) su propio kernel personalizado y eliminar todas las funciones que no están relacionadas con la ejecución del sistema y las redes. Querrá deshabilitar para bloquear la capa, no sé cómo hacer esto en los núcleos recientes make menuconfig.
  • Luego debe incluir su módulo en el núcleo para que se incluya como parte del núcleo y no como un módulo cargable. Probablemente deshabilitará los módulos cargables en el paso anterior. Si conoce suficiente C / C ++ para crear un módulo de kernel, esto debería ser fácil para usted.
  • Debe modificar cualquier parte del núcleo que entre en pánico si initno lo hace, o estar preparado para vivir con 1 proceso adicional de espacio de usuario.

Sé que es posible que los módulos del núcleo creen procesos: un simple ps auxmostraría muchos en un sistema típico (todos están entre paréntesis). Probablemente desee que su módulo cree un proceso de kernel. Para deshacerse de todos los procesos creados por el kernel además del suyo, deberá deshabilitar los subprocesos [ kthreadd], la administración de energía [ pm], la capa de eventos [ events] y otros.


Si desea una configuración más práctica del proceso de espacio de usuario kernel + 1, es posible.

Linux tiene una opción de línea de comando del núcleo llamada init=: esto es lo que el núcleo comenzará cuando termine de cargarse. El programa debe estar en el dispositivo raíz que se especifica con root=o en el initrd (cargado por su gestor de arranque).

Si este programa sale, Linux entrará en pánico, así que asegúrese de que nunca salga.

Muchas distribuciones modernas de Linux lo tienen configurado para que un initprograma en el initrd realice una inicialización adicional del espacio de usuario, antes de comenzar /sbin/inito /sbin/systemd. Tendrá que averiguar qué hace su distribución aquí (la información para Debian está aquí ) y dónde puede especificar el programa final de "transferencia", y desde allí puede indicarle que inicie su aplicación en lugar de inito systemd.

systemdadministra una gran cantidad de funcionalidades básicas, como compilar /dev, configurar el nombre de host y otras cosas, por lo que si es flexible, es posible que desee considerar la configuración systemdpara generar un solo proceso y, opcionalmente, reiniciarlo si falla. Si no me equivoco, básicamente lo hace para un solo usuario o modo de recuperación: inicia un shell.

Tendrá 2 procesos en ejecución ( systemdy su programa), pero el sistema no entrará en pánico si su programa se cierra o falla.

Considere también simplemente una instalación liviana de Debian: una instalación "netinst" no tiene mucho funcionamiento además del kernel, un shell y un par de servicios, o considere OpenWRT / LEDE, tiene un servidor web para Luci que se ejecuta por defecto y un acopla otros servicios pero se deshabilita fácilmente

LawrenceC
fuente