Pesquisa de site

Insights profundos do sistema "Ubuntu Linux" - Vemos isso?


LINUX como sabemos é um kernel e não um sistema operacional, vem com diversas distribuições como: Debian, Fedora, Ubuntu etc. e muito mais. O sistema operacional Ubuntu desenvolvido por Mark Shuttleworth é popularmente conhecido e amplamente utilizado por muitos. Além disso, por ser gratuito e de código aberto, sua nova versão é lançada anualmente, com a contribuição de milhares de desenvolvedores que contribuem para seu desenvolvimento. Mas, como funciona? Quais são todos os processos, lista de eventos que o fazem funcionar e qual é o significado desses processos?

Este artigo irá levá-lo um pouco mais fundo nos detalhes do Ubuntu OS que são muito interessantes e ajudariam um novato a ter uma compreensão completa de seu funcionamento.

Estabelecimento do Sistema

O Linux possui um processo para seu funcionamento, todo e qualquer serviço do sistema, incluindo gerenciamento de energia, inicialização, tratamento de falhas do sistema, é um processo que possui um arquivo de configuração em “/etc/init” que descreve o evento no qual ele executará o evento correspondente no qual interromperia sua execução, além de manter seus outros arquivos de configuração que descrevem seu comportamento em tempo de execução no diretório “/etc/” do sistema, tornando o sistema um evento orientado.

Se houver eventos gerados, alguém deveria estar lá para capturá-los e executá-los? Bem, obviamente, o controlador é o nosso processo principal que existe como pai de todos os processos com id de processo 1, ou seja, init. Este é o processo que começa com a inicialização do sistema e nunca para. Este processo só morre quando o sistema é desligado, pois não há nenhum processo pai do init.

Versões anteriores do Ubuntu anteriores à 6.10 incluíam o antigo estilo sysvinit que era usado para executar scripts em “/etc/rcx.d ” em cada inicialização e desligamento do sistema. Mas, depois disso, o sistema upstart substituiu o antigo sistema sysvinit, mas ainda fornece compatibilidade com versões anteriores.

As versões mais recentes do Ubuntu possuem este sistema inicial, mas desde sua evolução do Ubuntu 6.10 ele passou por várias revisões, sendo a versão atual 1.13.2 em 4 de setembro de 2014. O sistema inicial mais recente tem 2 processos init, um para os processos do sistema e outro que gerencia a sessão atual do usuário logado e existe apenas até o usuário estar logado, também chamado de x-session init .

Todo o sistema foi estabelecido como um sistema hierárquico, consistindo no relacionamento ancestral-filho ao longo de todo o sistema.

Por exemplo: Uma pequena relação hierárquica entre ambos os processos init é: system init(1) -> display manager(kernel space) -> gerenciador de exibição (espaço do usuário) -> inicialização do usuário (ou inicialização da sessão x).

Os arquivos de configuração para processos gerenciados pelo init do sistema residem em “/etc/init ” e para aqueles gerenciados pelo init da sessão residem em “/usr/share/upstart ” (como de acordo com as versões iniciais atuais acima de 1.12) e esses arquivos de configuração são fundamentais para muitos segredos descobertos sobre processos descritos neste artigo.

Aprofundando-se mais na hierarquia

O Ubuntu reconhece dois tipos de processos:

  1. Empregos de curta duração (ou empregos de trabalhar e morrer).
  2. Empregos de longa duração (ou empregos de permanência e trabalho).

A hierarquia que é feita no sistema se deve à relação de dependência entre os processos que podemos entender visualizando seus arquivos de configuração. Vamos primeiro partir de uma relação hierárquica simples entre os processos que fazem o sistema inicializar e entender o significado de cada um deles.

Hierarquia de inicialização

Init é o primeiro processo a iniciar ao ligar o sistema e é classificado no trabalho work-and-stay, pois nunca é encerrado e apenas o momento em que o init é encerrado é ativado desligando, ou seja, o init só morre e isso também uma vez por sessão e é desligado. Ao ligar, o init gera o primeiro evento no sistema, ou seja, evento de inicialização. Cada arquivo de configuração em “/etc/init” possui duas linhas que definem o evento que faz com que o processo inicie e pare. Essas linhas estão destacadas na figura abaixo:

Este é um arquivo de configuração de um processo failsafe-x e essas condições de início e parada descrevem o evento no qual o processo será iniciado. Na geração do evento de inicialização pelo processo init aqueles processos que têm inicialização como condição de início são executados em paralelo e isso apenas define a hierarquia, e todos os processos que executam na inicialização são filhos do init.

Os processos que iniciam na inicialização estão listados abaixo e são todos trabalhos de trabalho e morte:

1. hostname – Este é um processo que apenas informa ao sistema seu nome de host definido no arquivo /etc/hostname.

2. kmod – Carrega os módulos do kernel, ou seja, todos os drivers do arquivo /etc/modules.

3. mountall – Este processo gera muitos eventos e é o principal responsável pela montagem de todos os sistemas de arquivos na inicialização, incluindo sistemas de arquivos locais e sistemas de arquivos remotos.

O arquivo /proc também é montado por este mesmo processo e depois de todo o trabalho de montagem o último evento gerado por ele é o evento do sistema de arquivos que faz com que a hierarquia prossiga ainda mais.

4. plymouth – Este processo é executado ao iniciar o mountall e é responsável por mostrar aquela tela preta que aparece na inicialização do sistema mostrando algo como abaixo:

5. plymouth-ready – Indica que o plymouth está ativo.

A seguir estão os processos principais, outros que também são executados na inicialização incluem, como udev-fallback-graphics, etc. Voltando à hierarquia de inicialização, em poucas palavras, os eventos e processos a seguir são como em sequência:

1. init junto com a geração do evento de inicialização.

2. mountall montando sistemas de arquivos, plymouth (junto com o início do mountall) exibindo a tela inicial e kmod carregando módulos do kernel.

3. Evento local-filesystem gerado pelo mountall fazendo com que o dbus seja executado. (Dbus é o barramento de mensagens de todo o sistema que cria um soquete permitindo que outros processos se comuniquem entre si através do envio de mensagens para este soquete e o receptor escuta as mensagens neste soquete e filtra aquelas destinadas a ele).

4. local-filesystem junto com o dbus iniciado e o evento static-network-up causado pela rede do processo que também é executado no evento do sistema de arquivos local faz com que o gerenciador de rede seja executado.

5. O evento virtual-filesystem gerado pelo mountall faz com que o udev seja executado. (udev é o gerenciador de dispositivos para Linux que gerencia hot-plugging de dispositivos e é responsável por criar arquivos no diretório /dev e gerenciá-los também.) udev cria arquivos para ram, rom etc no diretório /dev aqueles que o mountall terminou de montar virtualmente -filesystems e gerou o evento virtual-filesystem que significa montagem do diretório /dev.

6. udev faz com que o upstart-udev-bridge seja executado, o que significa que a rede local está ativa. Então, depois que mountall terminar de montar o último sistema de arquivos e gerar o evento do sistema de arquivos.

7. O evento filesystem junto com o evento static-network-up faz com que o trabalho rc-sysinit seja executado. Aí vem a compatibilidade retroativa entre o sysvinit mais antigo e o iniciante…

9. rc-sysinit executa o comando telinit que informa o nível de execução do sistema.

10. Após obter o nível de execução, o init executa os scripts que começam com 'S' ou 'K' (iniciando jobs que possuem 'S' no no início do nome e matando aqueles que têm 'K' no início do nome) no diretório /etc/rcX.d (onde 'X' é o nível de execução atual) .

Este pequeno conjunto de eventos faz com que o sistema seja iniciado sempre que você o liga. E esse evento acionador de processos é o único responsável pela criação da hierarquia.

Agora, outro complemento acima é a causa do evento. Qual processo causa qual evento também é especificado no mesmo arquivo de configuração do processo, conforme mostrado abaixo nestas linhas:

Acima está uma seção do arquivo de configuração do processo mountall. Isso mostra os eventos que ele emite. O nome do evento é aquele que sucede a palavra ‘evento’. O evento pode ser aquele definido no arquivo de configuração acima ou pode ser o nome do processo junto com o prefixo ‘starting’, ‘started’, ‘stopping’ ou ‘stopped’.

Então, aqui definimos dois termos:

  1. Gerador de Eventos: Aquele que possui a linha ‘emits xxx’ em seu arquivo de configuração onde xxx é o nome do evento que ele possui ou gera.
  2. Event Catcher: Aquele que tem sua condição de início ou parada como xxx ou que inicia ou para no evento gerado em um dos geradores de eventos.

Assim segue a hierarquia e assim a dependência entre processos:

Event generator (parent) -> Event catcher (child)

Adicionando Complexidade à Hierarquia

Até agora, você deve ter entendido como a hierarquia de dependência pai-filho entre os processos é estabelecida pelo mecanismo de acionamento de eventos através de um mecanismo simples de inicialização.

Agora, esta hierarquia nunca é um relacionamento um-para-um, tendo apenas um pai para um filho. Nesta hierarquia podemos ter um ou mais pais para um filho ou um processo sendo pai de mais de um filho. Como isso é feito? Bem, a resposta está nos próprios arquivos de configuração.

Essas linhas são retiradas da rede de processo e aqui a condição de início parece um pouco complexa demais, composta de muitos eventos, a saber - sistemas de arquivos locais, udevtrigger, container, nível de execução, rede.

Sistemas de arquivos locais são emitidos por mountall, udevtrigger é o nome do trabalho, evento de contêiner é emitido por detecção de contêiner, evento de nível de execução emitido por rc-sysinit e rede é novamente um trabalho.

Assim, em uma hierarquia, a rede de processos é filha de mountall, udevtrigger e container-detect, pois não pode continuar seu funcionamento (o funcionamento do processo são todas as linhas definidas nas seções script ou exec no arquivo de configuração do processo) até que os processos acima gerem seus eventos.
Da mesma forma, podemos ter um processo sendo pai de muitos se o evento gerado por um processo for armazenado em cache por muitos.

Distinguir tipos de trabalho

Conforme definido anteriormente, podemos ter empregos de curta duração (ou empregos de trabalhar e morrer) ou de longa duração (ou ficar e trabalhar), mas como distinguir entre eles??

Os trabalhos que possuem as condições 'start on' e 'stop on' especificadas em seus arquivos de configuração e possuem a palavra 'task' em seus arquivo de configuração são jobs work-and-die que iniciam no evento gerado, executam seu script ou seção exec (durante a execução, eles bloqueiam os eventos que os causaram) e morrem depois liberando os eventos que eles bloquearam .

Aqueles trabalhos que não possuem a condição ‘parar em’ em seu arquivo de configuração são trabalhos de longa duração ou permanecem e trabalham e nunca morrem. Agora, os empregos de permanência e trabalho podem ser classificados ainda como:

  1. Aqueles que não possuem condição de respawn e podem ser eliminados pelo usuário root.
  2. Aqueles que possuem condição de respawn em seu arquivo de configuração e então reiniciam após serem eliminados, a menos que seu trabalho tenha sido concluído.

Conclusão

Assim, cada processo no LINUX é dependente de alguns e tem alguns processos dependentes dele e esse relacionamento é muitos sobre muitos e é especificado com o sistema inicial junto com outros detalhes do processo.