Este proyecto demuestra cómo crear rápidamente un sistema operativo Linux compacto y completamente funcional. La dirección del proyecto es https://github.com/supererconvert/smart-os

¿Por qué elegimos la versión del servidor para la producción?
La versión del servidor no contiene la mayoría de los paquetes de los que depende el sistema de ventanas; Si el sistema viene con estos paquetes, habrá problemas con múltiples versiones del paquete, problemas de compilación, problemas de dependencia, problemas de enlace y problemas de tiempo de ejecución, lo que causará mucha interferencia a nuestro trabajo. Además, resolver estos problemas no tiene sentido, necesitamos versiones puras de paquetes de dependencia
¿Por qué el sistema de ventanas funciona tan grande?
Todos los paquetes (excepto las herramientas) que instalamos utilizando APT, teóricamente, necesitamos compilar el código fuente, incluidas las dependencias y las adherencias del paquete, que deben resolverse. Esta es una carga de trabajo extremadamente grande. No hay forma de que no hay nada en el nuevo sistema, y el entorno requerido debe ser proporcionado por nosotros. El proyecto A depende del paquete B, el paquete B depende del paquete C, el paquete C y el paquete C depende del paquete d. ¡Todo lo que tenemos que hacer es compilar todos los paquetes!
Este guión se realizó en Ubuntu 18.04. Otros sistemas no deberían cambiar mucho. Los amigos que lo necesitan pueden modificarlo ellos mismos.
Prepare el entorno del sistema. Dado que el núcleo debe ser compilado, debe instalar el entorno requerido para la compilación del núcleo. Dado que BusyBox necesita ser compilado, puede instalar el entorno requerido usted mismo según sea necesario.
./00_build_env.shCompilar el código fuente (kernel, GLIBC, BusyBox, GCC, Binutils)
./01_build_src.shCree un disco del sistema (importante, este paso instala el sistema en un archivo del sistema)
./02_build_img.shEjecute el sistema Smart-OS
./03_run_qemu.sh 或 ./04_run_docker.sh¿Es fácil hacer un sistema operativo? El espacio en disco se puede ampliar arbitrariamente, se puede acceder en línea y se puede ampliar según sea necesario. Lo he probado con éxito y ejecutar el servidor de transmisión SMART_RTMPD en Smart-OS
+----------------------------------------------------------------+-----------------------------------------+-----------------------------------------+
| Host | Container 1 | Container 2 |
| | | |
| +------------------------------------------------+ | +-------------------------+ | +-------------------------+ |
| | Newwork Protocol Stack | | | Newwork Protocol Stack | | | Newwork Protocol Stack | |
| +------------------------------------------------+ | +-------------------------+ | +-------------------------+ |
| + + | + | + |
| ............... | .................... | ........................... | ................... | ..................... | .................... | .................... |
| + + | + | + |
| +-------------+ +---------------+ | +---------------+ | +---------------+ |
| | 192.168.0.3 | | 192.168.100.1 | | | 192.168.100.6 | | | 192.168.100.8 | |
| +-------------+ +---------------+ +-------+ | +---------------+ | +---------------+ |
| | eth0 | | br0 | < --- > | tap0 | | | eth0 | | | eth0 | |
| +-------------+ +---------------+ +-------+ | +---------------+ | +---------------+ |
| + + + | + | + |
| | | | | | | | |
| | + +------------------------------+ | | |
| | +-------+ | | | |
| | | tap1 | | | | |
| | +-------+ | | | |
| | + | | | |
| | | | | | |
| | +-------------------------------------------------------------------------------------------+ |
| | | | |
| | | | |
+--------------- | ------------------------------------------------+-----------------------------------------+-----------------------------------------+
+
Physical Network (192.168.0.0/24)Dado que Smart-OS instala la biblioteca dinámica GLIBC, esto se basa en gran medida en el cargador/enlazador dinámico LD-Linux-X86-64.So.2. Dado que las aplicaciones están vinculadas a través de la compilación dinámica, cuando el sistema operativo cargue una aplicación que requiere un enlace dinámico, el sistema debe ubicar y cargar todos los archivos dinámicos de la biblioteca que necesita. Este trabajo es realizado por LD-Linux.so.2. Cuando se carga el programa, el sistema operativo entregará el control a LD-Linux.so en lugar de la dirección de entrada normal del programa. LD-Linux.so.2 buscará y cargará todos los archivos de la biblioteca requeridos, y luego entregará el control al portal inicial de la aplicación. LD-Linux-X86-64.So.2 es en realidad la cadena suave de LD-Linux.so.2. Debe existir debajo /lib64/ld-linux-x86-64.so.2. De lo contrario, nuestro BusyBox compilado dinámicamente depende de la biblioteca GLIBC. La carga de la biblioteca GLIBC requiere LD-Linux-X86-64.SO. Si no existe en el directorio /lib64, hará que el sistema se cuente directamente. ¡Este problema necesita atención especial! ! !
QEMU generalmente tiene una pequeña ventana después del inicio. Una vez que ocurre un error, básicamente no hay forma de leer el registro de errores. Luego debe agregar consola = TTYS0 al elemento de inicio de la comida. Al mismo tiempo, QEMU-System-X86_64 agrega la salida del puerto serie al archivo de archivo: ./ qemu.log, por lo que la depuración es mucho más conveniente. Después de la depuración, debe eliminar la consola = TTYS0. De lo contrario, el contenido en /etc/init.d/rcs no puede mostrarse.
La versión de GLIBC que compilamos suele ser más alta que la versión que viene con el sistema. Podemos escribir un programa de prueba Main.c para probar si GLIBC se compila correctamente. Por ejemplo:
# include < stdio.h >
int main () {
printf ( " Hello glibc n " );
return 0 ;
}Compilamos
gcc -o test main.c -Wl,-rpath=/root/smart-os/work/glibc_install/usr/lib64 Ejecutamos el programa ./test correctamente, y generalmente informamos un error similar a este /lib64/libc.so.6: Versión `Glibc_2.28 'no encontrado o los segmentos del programa directamente. De hecho, esta es la razón por la que no hay un cargador de biblioteca dinámico especificado y un entorno de sistema. Por lo general, cuando compilamos la biblioteca GLIBC, el directorio de compilación generará automáticamente un archivo de script testRun.sh, y ejecutamos el programa en el directorio de compilación.
./testrun.sh ./test Esto generalmente se hace con éxito. También podemos guardar la siguiente oración en un script, y también está bien ejecutar la prueba.
exec env /root/smart-os/work/glibc_install/lib64/ld-linux-x86-64.so.2 --library-path /root/smart-os/work/glibc_install/lib64 ./test¿Cómo rastreamos qué bibliotecas cargadas por un programa ejecutable? Solo use ld_debug = libs ./test. Precedimos la biblioteca y obligamos a precargar la biblioteca a usar ld_preload para forzar la biblioteca
Cuando compilamos El Cairo, generalmente encontramos muchos problemas. ¿Qué debemos hacer si hay un problema con la compilación de El Cairo? Algunos mensajes de error son difíciles de buscar en Internet para ver el archivo config.log generado durante la compilación. ¡Los mensajes de error son muy detallados! Puede resolver el problema de acuerdo con la información rápida
Sobre las variables del sistema init de BusyBox, incluso si se utilizan los parámetros del núcleo de Grub, no es posible pasar las variables de entorno. El init de BusyBox generará automáticamente la ruta de variable de entorno predeterminada, por lo que el código fuente debe cambiarse para admitir rutas personalizadas. Por supuesto, el modo de inicio de sesión del shell leerá /etc /perfil. Para el modo no login, este modo no es válido, por lo que hay limitaciones para pasar /etc /perfil.
Este conocimiento implica un conocimiento relativamente grande. Hay relativamente pocos artículos que introducen específicamente la compilación y el uso de XFCE4 en China, incluso en el extranjero. También cruzé el río sintiendo las piedras e intenté demostrar este conocimiento claramente. Abriré un capítulo especial para explicar esto. Para el trasplante de XFCE4 a Smart-OS, revelará los secretos del sistema de gráficos a los chinos. Para más detalles, consulte XFCE4.MD.
La carga de trabajo de integración de todo el sistema de gráficos es particularmente enorme, que involucra todos los aspectos del sistema. Hay relativamente poca información sistemática sobre este aspecto en el extranjero, y casi incluso menos en China. El objetivo es hacer bricolaje en todos los entornos y proyectos personales de código abierto para que todo el sistema de gráficos se ejecute intacto. Smart-OS no es el primero, pero son básicamente los tres primeros. No lo sé todavía. Todo el proceso de integración es muy largo y encontré muchos problemas. No hablaré sobre estas tareas repetitivas a través de la depuración continua y la compilación. La carga de trabajo es particularmente enorme. Casi puedo describir mi trabajo duro. No es absolutamente una exageración describir mi trabajo. En segundo lugar, encontré muchos puntos de conocimiento, muchos de los cuales fueron aprendidos y vendidos de inmediato. Necesitaba comprender rápidamente el mecanismo de trabajo, causar el problema y luego resolver el problema. Hablemos aproximadamente sobre la idea general, que facilitará a los nuevos académicos para comprender rápidamente las ideas, proporcionar orientación sobre el mantenimiento del sistema y proporcionar un modelo para resolver problemas del sistema.
El directorio de USR detalla la abreviatura del recurso del sistema USR = UNIX. La biblioteca /lib es una biblioteca a nivel de kernel, /usr /lib es una biblioteca a nivel de sistema, y /usr /local /lib es una biblioteca a nivel de aplicación; /lib contiene muchas bibliotecas utilizadas por programas ejecutables en /bin && /sbin. /USR/LIB Casi todas las bibliotecas a las que se realiza los programas ejecutables del sistema se instalan aquí, y/USR/local/bin Muchas bibliotecas a las que se realizan programas ejecutables a nivel de aplicación se colocan aquí
RAMFS:
RAMFS es un sistema de archivos muy simple. Utiliza directamente el mecanismo de caché existente del kernel de Linux (por lo que su código de implementación es muy pequeño. Por esta razón, la función RAMFS no puede bloquearse a través de parámetros de configuración del núcleo. Es una propiedad natural del núcleo). Utiliza la memoria física del sistema para hacer un sistema de archivos basado en la memoria con un tamaño dinámico. El sistema no lo reciclará, y solo los usuarios de raíces lo usan.
TMPFS:
TMPFS es un derivado de RAMFS, que agrega límites de capacidad y permite que los datos se escriban en swaps basados en RAMF. Debido a la adición de estas dos características, los usuarios comunes también pueden usar TMPFS. TMPFS ocupa la memoria virtual, no toda RAM, y su rendimiento puede no ser tan alto como RAMFS
Ramdisk:
Ramdisk es una tecnología que utiliza un área en la memoria como disco físico. También se puede decir que RamDisk es un dispositivo de bloque creado en un trozo de memoria para almacenar sistemas de archivos. Para los usuarios, Ramdisk se puede tratar por igual con la partición de disco duro habitual. El sistema también almacenará un caché correspondiente en la memoria, contaminando el caché de la CPU, el bajo rendimiento y requerirá el soporte del controlador correspondiente.
Rootfs:
RootFS es una instancia de RAMFS específica (o TMPFS, si TMPFS está habilitado), siempre existe en los sistemas Linux2.6. Los rootfs no se pueden desinstalar (en lugar de agregar un código especial para mantener listas vinculadas vacías, es mejor agregar siempre nodos rootfs, por lo que es conveniente para el mantenimiento del núcleo. Rootfs es una instancia vacía de RAMFS y ocupa muy poco espacio). La mayoría de los otros sistemas de archivos se instalan en rootfs y luego lo ignoran. Es la inicialización de inicio del núcleo del sistema de archivos raíz.
Los raíces se dividen en raíces virtuales y raíces reales.
Las raíces virtuales son creadas y cargadas por el kernel en sí y solo existen en la memoria (el initRAMFS posterior también se implementa sobre esta base), y su sistema de archivos es de tipo TMPFS o tipo RAMFS.
RootFS real significa que el sistema de archivos raíz existe en el dispositivo de almacenamiento. Durante el proceso de inicio, el núcleo montará este dispositivo de almacenamiento en los raíces virtuales y luego cambiará el nodo / directorio a este dispositivo de almacenamiento. De esta manera, el sistema de archivos en el dispositivo de almacenamiento se utilizará como el sistema de archivos raíz (el initramdisk posterior se implementa sobre esta base), y sus tipos de sistema de archivos son más ricos, que pueden ser ext2, yaffs, yaffs2, etc., que están determinados por el tipo del dispositivo de almacenamiento específico.
Nuestro sistema de archivos de inicio es en realidad preparar archivos para rootfs, para que el kernel pueda ejecutarse como lo deseamos. En los primeros sistemas de Linux, solo los discos duros o los discos disquetes generalmente se usaron como dispositivos de almacenamiento para el sistema de archivos raíz de Linux, por lo que es fácil integrar los controladores de estos dispositivos en el núcleo. Sin embargo, en los sistemas integrados de hoy, el sistema de archivos raíz se puede guardar en varios dispositivos de almacenamiento, incluidos SCSI, SATA, U-Disk, etc. Por lo tanto, obviamente no es muy conveniente compilar todo el código del controlador de estos dispositivos en el núcleo. En el mecanismo de carga automática del módulo del núcleo UDEV, vemos que UDEVD puede realizar la carga automática del módulo del núcleo, por lo que esperamos que si el controlador del dispositivo de almacenamiento almacena el sistema de archivos raíz también puede realizar la carga automática, sería genial. Sin embargo, hay una contradicción aquí. UDEVD es un archivo ejecutable. Es imposible ejecutar UDEVD antes de montar el sistema de archivos raíz. Sin embargo, si no se inicia UDEVD, el controlador que almacena el dispositivo del sistema de archivos raíz no se puede cargar automáticamente, y el nodo del dispositivo correspondiente no se puede establecer en el directorio /dev. Para resolver esta contradicción, surgió un initrd basado en Ramdisk (disco RAM inicializado de Bootloader). InitRD es un directorio de raíz pequeña compactada. Este directorio contiene los módulos de controlador necesarios, los archivos ejecutables y los scripts de inicio en la etapa de inicio, y también incluye el UDEVD (demonio que implementa el mecanismo UDEV). Cuando se inicia el sistema, el gestor de arranque leerá el archivo initrd en la memoria y luego pasará la dirección de inicio y el tamaño del archivo initrd en la memoria al kernel. Durante el proceso de inicialización, el kernel descomprimirá el archivo initrd, luego montará el initrd descomprimido como el directorio raíz y luego ejecutará el script /init en el directorio raíz (init en formato CPIO es /initrd en formato de imagen <también conocido como initrd de bloques antiguos o initrd en el formato de archivo tradicional es /initrc). Puede ejecutar UDEVD en el sistema de archivos initrd en este script, dejar que cargue automáticamente los controladores RealFS (sistema de archivos real) para almacenar el dispositivo y establecer los nodos del dispositivo necesarios en el directorio /dev directorio. Después de que UDEVD carga automáticamente el controlador de disco, puede montar el directorio de raíz real y cambiar a este directorio raíz.