Eso depende completamente de los servicios que desee tener en su dispositivo.
Programas
Puede hacer que Linux arranque directamente en un shell . No es muy útil en producción, ¿quién querría tener un caparazón ahí?, pero es útil como mecanismo de intervención cuando tienes un cargador de arranque interactivo:pasa init=/bin/sh
a la línea de comandos del núcleo. Todos los sistemas Linux (y todos los sistemas Unix) tienen un shell estilo Bourne/POSIX en /bin/sh
.
Necesitará un conjunto de utilidades de shell . BusyBox es una opción muy común; contiene un shell y utilidades comunes para la manipulación de archivos y texto (cp
, grep
, …), configuración de red (ping
, ifconfig
, …), manipulación de procesos (ps
, nice
, …) y varias otras herramientas del sistema (fdisk
, mount
, syslogd
, …). BusyBox es extremadamente configurable:puede seleccionar qué herramientas desea e incluso características individuales en el momento de la compilación, para obtener el compromiso de tamaño/funcionalidad adecuado para su aplicación. Aparte de sh
, lo mínimo sin lo que realmente no puedes hacer nada es mount
, umount
y halt
, pero sería atípico no tener también cat
, cp
, mv
, rm
, mkdir
, rmdir
, ps
, sync
y algunos más. BusyBox se instala como un único binario llamado busybox
, con un enlace simbólico para cada utilidad.
El primer proceso en un sistema Unix normal se llama init
. Su trabajo es iniciar otros servicios. BusyBox contiene un sistema de inicio. Además del init
binario (generalmente ubicado en /sbin
), necesitará sus archivos de configuración (generalmente llamados /etc/inittab
— algunos reemplazos de inicio modernos eliminan ese archivo pero no los encontrará en un sistema integrado pequeño) que indican qué servicios iniciar y cuándo. Para BusyBox, /etc/inittab
es opcional; si falta, obtienes un shell raíz en la consola y el script /etc/init.d/rcS
(ubicación predeterminada) se ejecuta en el momento del arranque.
Eso es todo lo que necesitas, más allá, por supuesto, de los programas que hacen que tu dispositivo haga algo útil. Por ejemplo, en el enrutador de mi casa que ejecuta una variante de OpenWrt, los únicos programas son BusyBox, nvram
(para leer y cambiar configuraciones en NVRAM) y utilidades de red.
A menos que todos sus ejecutables estén vinculados estáticamente, necesitará el cargador dinámico (ld.so
, que pueden recibir diferentes nombres dependiendo de la elección de libc y de las arquitecturas del procesador) y todas las bibliotecas dinámicas (/lib/lib*.so
, tal vez algunos de estos en /usr/lib
) requerido por estos ejecutables.
Estructura de directorios
El estándar de jerarquía del sistema de archivos describe la estructura de directorio común de los sistemas Linux. Está orientado a instalaciones de escritorio y servidor:gran parte se puede omitir en un sistema integrado. Aquí hay un mínimo típico.
/bin
:programas ejecutables (algunos pueden estar en/usr/bin
en su lugar)./dev
:nodos de dispositivo (ver más abajo)/etc
:archivos de configuración/lib
:bibliotecas compartidas, incluido el cargador dinámico (a menos que todos los ejecutables estén vinculados estáticamente)/proc
:punto de montaje para el sistema de archivos proc/sbin
:programas ejecutables. La distinción con/bin
es que/sbin
es para programas que solo son útiles para el administrador del sistema, pero esta distinción no es significativa en dispositivos integrados. Puedes hacer/sbin
un enlace simbólico a/bin
./mnt
:útil para tener en sistemas de archivos raíz de solo lectura como un punto de montaje temporal durante el mantenimiento/sys
:punto de montaje para el sistema de archivos sysfs/tmp
:ubicación de archivos temporales (a menudo untmpfs
montar)/usr
:contiene subdirectoriosbin
,lib
ysbin
./usr
existe para archivos adicionales que no están en el sistema de archivos raíz. Si no tienes eso, puedes hacer/usr
un enlace simbólico al directorio raíz.
Archivos de dispositivo
Aquí hay algunas entradas típicas en un mínimo /dev
:
console
full
(escribir en él siempre informa "no queda espacio en el dispositivo")log
(un socket que los programas usan para enviar entradas de registro), si tiene unsyslogd
daemon (como el de BusyBox) leyendo de élnull
(actúa como un archivo que siempre está vacío)ptmx
y unpts
directorio, si desea utilizar pseudo-terminales (es decir, cualquier terminal que no sea la consola), p. si el dispositivo está conectado a la red y desea conectarse mediante telnet o sshrandom
(devuelve bytes aleatorios, corre el riesgo de bloquearse)tty
(siempre designa la terminal del programa)urandom
(devuelve bytes aleatorios, nunca bloquea, pero puede no ser aleatorio en un dispositivo recién iniciado)zero
(contiene una secuencia infinita de bytes nulos)
Más allá de eso, necesitará entradas para su hardware (excepto las interfaces de red, estas no obtienen entradas en /dev
):puertos serie, almacenamiento, etc.
Para los dispositivos integrados, normalmente crearía las entradas del dispositivo directamente en el sistema de archivos raíz. Los sistemas de gama alta tienen un script llamado MAKEDEV
para crear /dev
entradas, pero en un sistema incrustado, la secuencia de comandos a menudo no se incluye en la imagen. Si algún hardware se puede conectar en caliente (por ejemplo, si el dispositivo tiene un puerto host USB), entonces /dev
debe ser administrado por udev (es posible que aún tenga un conjunto mínimo en el sistema de archivos raíz).
Acciones en tiempo de arranque
Más allá del sistema de archivos raíz, debe montar algunos más para el funcionamiento normal:
- procfs en
/proc
(bastante indispensable) - sysfs en
/sys
(bastante indispensable) tmpfs
sistema de archivos en/tmp
(para permitir que los programas creen archivos temporales que estarán en la RAM, en lugar de en el sistema de archivos raíz, que puede estar en flash o de solo lectura)- tmpfs, devfs o devtmpfs en
/dev
si es dinámico (consulte udev en "Archivos de dispositivo" más arriba) - devpts en
/dev/pts
si quiere usar [pseudo-terminales (vea el comentario sobrepts
arriba)
Puedes hacer un /etc/fstab
archivar y llamar mount -a
o ejecuta mount
manualmente.
Inicie un demonio syslog (así como klogd
para los registros del kernel, si el syslogd
programa no se ocupa de eso), si tiene algún lugar para escribir registros.
Después de esto, el dispositivo está listo para iniciar los servicios específicos de la aplicación.
Cómo hacer un sistema de archivos raíz
Esta es una historia larga y diversa, así que todo lo que haré aquí será dar algunos consejos.
El sistema de archivos raíz se puede mantener en la RAM (cargado desde una imagen (generalmente comprimida) en ROM o flash), o en un sistema de archivos basado en disco (almacenado en ROM o flash), o cargado desde la red (a menudo a través de TFTP) si corresponde. . Si el sistema de archivos raíz está en RAM, conviértalo en initramfs, un sistema de archivos RAM cuyo contenido se crea en el momento del arranque.
Existen muchos marcos para ensamblar imágenes raíz para sistemas integrados. Hay algunos consejos en las preguntas frecuentes de BusyBox. Buildroot es popular y le permite crear una imagen raíz completa con una configuración similar al kernel de Linux y BusyBox. OpenEmbedded es otro marco de este tipo.
Wikipedia tiene una lista (incompleta) de distribuciones populares de Linux integradas. Un ejemplo de Linux incorporado que puede tener cerca de usted es la familia de sistemas operativos OpenWrt para dispositivos de red (popular en los enrutadores domésticos de los aficionados). Si desea aprender por experiencia, puede probar Linux from Scratch, pero está orientado a sistemas de escritorio para aficionados en lugar de dispositivos integrados.
Una nota sobre Linux vs Kernel de Linux
El único comportamiento integrado en el kernel de Linux es el primer programa que se inicia en el momento del arranque. (No entraré en las sutilezas de initrd e initramfs aquí.) Este programa, tradicionalmente llamado init, tiene ID de proceso 1 y tiene ciertos privilegios (inmunidad a señales KILL) y responsabilidades (cosechar huérfanos). Puede ejecutar un sistema con un kernel de Linux y comenzar lo que quiera como primer proceso, pero luego lo que tiene es un sistema operativo basado en el kernel de Linux, y no lo que normalmente se llama "Linux":Linux, en el sentido común. del término, es un sistema operativo similar a Unix cuyo kernel es el kernel de Linux. Por ejemplo, Android es un sistema operativo que no es similar a Unix sino que se basa en el kernel de Linux.
Todo lo que necesita es un ejecutable vinculado estáticamente, colocado en el sistema de archivos, de forma aislada. No necesita ningún otro archivo. Ese ejecutable es el proceso de inicio. Puede ser una caja ocupada. Eso le brinda un shell y una serie de otras utilidades, todo en sí mismo. Puede ir a un sistema en pleno funcionamiento simplemente ejecutando comandos manualmente en busybox para montar el sistema de archivos raíz de lectura y escritura, crear nodos /dev, ejecutar inicio real, etc.
Si no necesita ninguna utilidad de shell, un enlace estático mksh
binario (por ejemplo, contra klibc - 130K en Linux/i386) servirá. Necesitas un /linuxrc
o /init
o /sbin/init
script que simplemente llama a mksh -l -T!/dev/tty1
en un bucle:
#!/bin/mksh
while true; do
/bin/mksh -l -T!/dev/tty1
done
El -T!$tty
la opción es una adición reciente a mksh
eso le dice que genere un nuevo caparazón en el terminal dado y que lo espere. (Antes de eso, solo había -T-
para demonizar un programa y -T$tty
para engendrar en una terminal pero no esperarlo. Esto no fue tan agradable.) El -l
La opción simplemente le dice que ejecute un shell de inicio de sesión (que dice /etc/profile
, ~/.profile
y ~/.mkshrc
).
Esto supone que su terminal es /dev/tty1
, sustituto. (Con más magia, la terminal se puede descubrir automáticamente. /dev/console
no le dará el control total del trabajo.)
Necesita algunos archivos en /dev
para que esto funcione:
- /dev/consola
- /dev/null
- /dev/tty
- /dev/tty1
Arrancando con la opción del kernel devtmpfs.mount=1
elimina la necesidad de un /dev
completo , solo deja que sea un directorio vacío (adecuado para usar como punto de montaje).
Normalmente querrá tener algunas utilidades (de klibc, busybox, beastiebox, toybox o toolbox), pero en realidad no son necesarias.
Es posible que desee agregar un ~/.mkshrc
archivo, que configura $PS1 y algunos alias y funciones básicas de shell.
Una vez hice un initrd de 171K comprimido (371K sin comprimir) para Linux/m68k usando mksh (y su archivo mkshrc de muestra) y klibc-utils solamente. (Sin embargo, esto fue antes de que se agregara -T! al shell, por lo que generó el shell de inicio de sesión en /dev/tty2
en su lugar y envió un mensaje a la consola que le decía al usuario que cambiara de terminal.) Funciona bien.
Este es un mínimo realmente básico configuración. Las otras respuestas brindan excelentes consejos sobre sistemas algo más destacados. Esto es un caso especial real.
Descargo de responsabilidad:soy el desarrollador de mksh.