Este projeto demonstra como criar rapidamente um sistema operacional compacto e totalmente funcional. O endereço do projeto é https://github.com/superconvert/smart-os

Por que escolhemos a versão do servidor para produção?
A versão do servidor não contém a maioria dos pacotes dos quais o sistema de janelas depende; Se o sistema vier com esses pacotes, haverá problemas com várias versões do pacote, problemas de compilação, problemas de dependência, problemas de ligação e problemas de tempo de execução, o que causará muita interferência ao nosso trabalho. Além disso, resolver esses problemas não tem sentido, precisamos de versões puras de pacotes de dependência
Por que o sistema de janelas funciona tão grande?
Todos os pacotes (exceto ferramentas) que instalamos usando o APT, teoricamente, precisamos compilar o código -fonte, incluindo as dependências e aderências do pacote, que precisam ser resolvidas. Esta é uma carga de trabalho extremamente enorme. Não há como não há nada no novo sistema e o ambiente necessário precisa ser fornecido por nós. O projeto A depende do pacote B, o pacote B depende do pacote c, o pacote C e o pacote C depende do pacote d. Tudo o que precisamos fazer é compilar todos os pacotes!
Este script foi feito no Ubuntu 18.04. Outros sistemas não devem ser muito alterados. Amigos que precisam podem modificá -lo.
Prepare o ambiente do sistema. Como o kernel precisa ser compilado, você precisa instalar o ambiente necessário para a compilação do kernel. Como o BusyBox precisa ser compilado, você pode instalar o ambiente necessário, conforme necessário.
./00_build_env.shCompilar código -fonte (Kernel, Glibc, BusyBox, GCC, Binutils)
./01_build_src.shCrie um disco do sistema (importante, esta etapa instala o sistema em um arquivo do sistema)
./02_build_img.shExecute o sistema Smart-O
./03_run_qemu.sh 或 ./04_run_docker.shÉ fácil fazer um sistema operacional? O espaço do disco pode ser expandido arbitrariamente, pode ser acessado on -line e pode ser expandido conforme necessário. Eu tentei com sucesso e execute o servidor de streaming smart_rtmpd em 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)Como o Smart-OS instala a biblioteca dinâmica do GLIBC, isso se baseia fortemente no carregador dinâmico da biblioteca/vinculador LD-Linux-x86-64.so.2. Como os aplicativos são vinculados através da compilação dinâmica, quando um aplicativo que requer vinculação dinâmica é carregada pelo sistema operacional, o sistema deve localizar e carregar todos os arquivos de biblioteca dinâmica necessários. Este trabalho é realizado por ld-linux.so.2. Quando o programa é carregado, o sistema operacional entregará o controle ao LD-linux.so em vez do endereço de entrada normal do programa. LD-linux.so.2 procurará e carregará todos os arquivos de biblioteca necessários e, em seguida, entregará o controle no portal de partida do aplicativo. LD-linux-x86-64.so.2 é na verdade a cadeia macia de LD-linux.so.2. Ele deve existir em /lib64/ld-linux-x86-64.so.2. Caso contrário, nossa caixa ocupada dinamicamente compilada depende da biblioteca GLIBC. O carregamento da biblioteca GLIBC requer LD-Linux-X86-64.so. Se não existir no diretório /lib64, ele fará com que o sistema seja diretamente em pano. Esta questão precisa de atenção especial! ! !
Qemu geralmente tem uma pequena janela após a inicialização. Depois que ocorre um erro, basicamente não há como ler o log de erros. Então você precisa adicionar console = ttys0 ao item de inicialização do GRUB. Ao mesmo tempo, o Qemu-System-X86_64 adiciona saída de porta serial ao arquivo-serial: ./ qemu.log, então a depuração é muito mais conveniente. Após a depuração, você precisa remover o console = ttys0. Caso contrário, o conteúdo em /etc/init.d/rcs não pode ser exibido.
A versão do GLIBC que compilamos geralmente é maior que a versão que acompanha o sistema. Podemos escrever um programa de teste principal.c para testar se o GLIBC é compilado com sucesso. por exemplo:
# include < stdio.h >
int main () {
printf ( " Hello glibc n " );
return 0 ;
}Nós compilamos
gcc -o test main.c -Wl,-rpath=/root/smart-os/work/glibc_install/usr/lib64 Executamos o programa ./test com sucesso e geralmente relatamos um erro semelhante a este /lib64/libc.so.6: versão `glibc_2.28 'não encontrada ou os segmentos do programa diretamente. De fato, essa é a razão pela qual não há carregador/ligante dinâmico especificado e ambiente do sistema. Geralmente, quando compilamos a biblioteca GLIBC, o diretório de compilação gera automaticamente um arquivo de script testrun.sh e executamos o programa no diretório de compilação.
./testrun.sh ./test Isso geralmente é feito com sucesso. Também podemos salvar a seguinte frase em um script, e também é bom executar o teste.
exec env /root/smart-os/work/glibc_install/lib64/ld-linux-x86-64.so.2 --library-path /root/smart-os/work/glibc_install/lib64 ./testComo rastreamos quais bibliotecas carregadas por um programa executável? Basta usar ld_debug = libs ./test. Pré -carregamos a biblioteca e forçamos a pré -carga da biblioteca a usar LD_PRELOAD para forçar a pré -carga da biblioteca
Quando compilamos o Cairo, geralmente encontramos muitos problemas. O que devemos fazer se houver um problema com a compilação do Cairo? Algumas mensagens de erro são difíceis de pesquisar na Internet para ver o arquivo config.log gerado durante a compilação. As mensagens de erro são muito detalhadas! Você pode resolver o problema de acordo com as informações rápidas
Sobre as variáveis do sistema init de BusyBox, mesmo que os parâmetros do kernel do GRUB sejam usados, não é possível passar variáveis de ambiente. O Init do BusyBox gerará automaticamente o caminho da variável de ambiente padrão, portanto o código -fonte precisa ser alterado para suportar caminhos personalizados. Obviamente, o modo de login do shell lerá /etc /perfil. Para o modo que não é login, esse modo é inválido, portanto, há limitações para passar /etc /perfil.
Esse conhecimento envolve conhecimento relativamente grande. Existem relativamente poucos artigos que introduzem especificamente a compilação e o uso do XFCE4 na China, incluindo no exterior. Também atravessei o rio sentindo as pedras e tentei demonstrar esse conhecimento claramente. Vou abrir um capítulo especial para explicar isso. Para o transplante XFCE4 para o SMART-OS, ele revelará os segredos do sistema gráfico para os chineses. Para detalhes, consulte o XFCE4.MD.
A carga de trabalho de integração de todo o sistema gráfica é particularmente enorme, envolvendo todos os aspectos do sistema. Há relativamente pouca informação sistemática sobre esse aspecto no exterior e quase menos na China. O objetivo é DIY todos os ambientes e projetos pessoais de código aberto para tornar intacto todo o sistema gráfico. O Smart-OS não é o primeiro, mas é basicamente os três primeiros. Eu ainda não sei. Todo o processo de integração é muito longo e encontrei muitos problemas. Não vou falar sobre essas tarefas repetitivas por meio de depuração e compilação contínuas. A carga de trabalho é particularmente enorme. Quase posso descrever meu trabalho. Não é absolutamente um exagero descrever meu trabalho. Em segundo lugar, encontrei muitos pontos de conhecimento, muitos dos quais foram aprendidos e vendidos imediatamente. Eu precisava entender rapidamente o mecanismo de trabalho, causar o problema e depois resolver o problema. Vamos falar sobre a idéia geral aproximadamente, que facilitará novos estudiosos a entender rapidamente as idéias, fornecer orientações sobre a manutenção do sistema e fornecer um modelo para resolver problemas do sistema.
O diretório USR detalha a abreviação de USR = recurso do sistema UNIX. A biblioteca /lib é uma biblioteca de nível de kernel, /usr /lib é uma biblioteca em nível de sistema e /usr /local /lib é uma biblioteca no nível do aplicativo; /Lib contém muitas bibliotecas usadas por programas executáveis em /bin && /sbin. /usr/lib quase todas as bibliotecas mencionadas por programas executáveis do sistema são instalados aqui e/usr/local/bin muitas bibliotecas mencionadas por programas executáveis no nível do aplicativo são colocados aqui
Ramfs:
Ramfs é um sistema de arquivos muito simples. Ele utiliza diretamente o mecanismo de cache existente do kernel Linux (para que seu código de implementação seja muito pequeno. Por esse motivo, o recurso RAMFS não pode ser bloqueado através dos parâmetros de configuração do kernel. É uma propriedade natural do kernel). Ele usa a memória física do sistema para criar um sistema de arquivos baseado em memória com tamanho dinâmico. O sistema não o reciclará e apenas os usuários root o usarão.
TMPFS:
O TMPFS é um derivado do RAMFS, que adiciona limites de capacidade e permite que os dados sejam gravados em swaps com base no RAMFS. Devido à adição desses dois recursos, os usuários comuns também podem usar o TMPFS. O TMPFS ocupa a memória virtual, nem toda a RAM, e seu desempenho pode não ser tão alto quanto Ramfs
Ramdisk:
O RamDisk é uma tecnologia que usa uma área na memória como um disco físico. Também se pode dizer que o RamDisk é um dispositivo de bloco criado em uma peça de memória para armazenar sistemas de arquivos. Para os usuários, o RamDisk pode ser tratado igualmente com a partição usual de disco rígido. O sistema também armazenará um cache correspondente na memória, poluindo o cache da CPU, o desempenho ruim e exigirá suporte de driver correspondente.
rootfs:
Rootfs é uma instância de RAMFs específicos (ou TMPFs, se o TMPFS estiver ativado), ele sempre existe nos sistemas Linux2.6. O rootfs não pode ser desinstalado (em vez de adicionar código especial para manter listas vinculadas vazias, é melhor sempre adicionar nós rootfs, por isso é conveniente para a manutenção do kernel. Rootfs é uma instância vazia dos RAMFs e ocupa muito pouco espaço). A maioria dos outros sistemas de arquivos é instalada no Rootfs e depois o ignora. É a inicialização da inicialização do kernel do sistema de arquivos raiz.
Os rootfs são divididos em rootfs virtuais e rootfs reais.
Os rootfs virtuais são criados e carregados pelo próprio kernel e existem apenas na memória (o Initramfs subsequente também é implementado nessa base), e seu sistema de arquivos é do tipo tmpfs ou tipo RAMFS.
Rootfs reais significa que o sistema de arquivos raiz existe no dispositivo de armazenamento. Durante o processo de inicialização, o kernel montará este dispositivo de armazenamento no rootfs virtual e depois alternará o nó / diretório para este dispositivo de armazenamento. Dessa forma, o sistema de arquivos no dispositivo de armazenamento será usado como o sistema de arquivos raiz (o initramdisk subsequente é implementado nessa base) e seus tipos de sistema de arquivos são mais ricos, que podem ser ext2, yaffs, yaffs2, etc., que são determinados pelo tipo do dispositivo de armazenamento específico.
Nosso sistema de arquivos de inicialização é realmente preparar arquivos para o rootfs, para que o kernel possa ser executado como desejamos. Nos primeiros sistemas Linux, apenas discos rígidos ou discos de disquete eram geralmente usados como dispositivos de armazenamento para o sistema de arquivos raiz do Linux; portanto, é fácil integrar os fatores drivers desses dispositivos no kernel. No entanto, nos sistemas incorporados de hoje, o sistema de arquivos raiz pode ser salvo em vários dispositivos de armazenamento, incluindo SCSI, SATA, U-Disk etc. Portanto, obviamente não é muito conveniente compilar todo o código do driver desses dispositivos no kernel. No mecanismo automático de carregamento do módulo do kernel, vemos que o UDEVD pode realizar o carregamento automático do módulo do kernel, portanto, esperamos que, se o driver do dispositivo de armazenamento que armazenar o sistema de arquivos raiz também puder realizar o carregamento automático, isso fosse ótimo. No entanto, há uma contradição aqui. udevd é um arquivo executável. É impossível executar o UDEVD antes que o sistema de arquivos raiz seja montado. No entanto, se o UDEVD não for iniciado, o driver que armazena o dispositivo do sistema de arquivo raiz não poderá ser carregado automaticamente e o nó do dispositivo correspondente não poderá ser estabelecido no diretório /dev. Para resolver essa contradição, surgiu um initrd baseado em Ramdisk (BootLoader inicializado em disco RAM). Initrd é um diretório raiz pequeno compactado. Este diretório contém os módulos de driver necessários, arquivos executáveis e scripts de inicialização no estágio de inicialização e também inclui o UDEVD (demônio que implementa o mecanismo UDEV). Quando o sistema é iniciado, o carregador de inicialização lerá o arquivo initrd na memória e depois passa o endereço de início e o tamanho do arquivo initrd na memória para o kernel. Durante o processo de inicialização, o kernel descompactará o arquivo initrd e depois montará o Initrd desconfiado como o diretório raiz e executará o script /init no diretório raiz (init em formato CPIO é /init, enquanto o initrd no formato de imagem <também conhecido como initrd de blocos antigos ou ingresso no formato de arquivo tradicional> é /também é o formato de arquivo. Você pode executar o UDEVD no sistema de arquivos initrd neste script, que ele carregue automaticamente os drivers Realfs (sistema de arquivo real) para armazenar o dispositivo e estabelecer os nós do dispositivo necessários no diretório /dev. Depois que o UDEVD carrega automaticamente o driver de disco, você pode montar o diretório raiz real e alternar para este diretório raiz.