"Espaço de usuário" refere-se ao ambiente de execução de processos normais (contrário ao kernel). Isso não significa necessariamente que os usuários iniciaram estes processos, pois um sistema padrão rotineiramente tem vários processos "daemon" (serviços) em execução antes do usuário mesmo abrir uma sessão. Processos Daemon são processos no espaço do usuário.
Quando o kernel passa por sua fase de inicialização, ele inicia o primeiro processo, o init
. O processo #1 raramente é útil por si só, e em sistemas similares ao Unix executam com um ciclo de vida completo de processos.
Em primeiro lugar, um processo pode se clonar (isto é conhecido como fork). O kernel aloca um novo, mas idêntico, espaço de memória do processo, e um outro processo para usá-lo. Neste momento, a única diferença entre esses dois processos é o seu pid. O novo processo é costumeiramente chamado de um processo filho, e o processo cujo pid não muda, é chamado de processo pai.
Às vezes, o processo filho continua vida de forma independente de seu pai, com os seus próprios dados copiados do processo pai. Em muitos casos, porém, este processo filho executa outro programa. Com poucas exceções, sua memória é simplesmente substituída pela do novo programa, e a execução deste novo programa começa. Uma das primeiras ações do processo número 1, por exemplo, é o de duplicar-se (o que significa que há, por um pequeno período de tempo, duas cópias de funcionamento do mesmo processo
init
), mas o processo filho é então substituído pelo primeiro script de inicialização do sistema, normalmente
/etc/init.d/rcS
. Esse script, por sua vez, clona-se e executa vários outros programas. Em algum momento, um dos processos descendentes do
init
começa uma interface gráfica para os usuários iniciarem sua sessão (a sequência dos eventos é descrito em mais detalhes no
Seção 9.1, “Inicialização do Sistema”).
Quando um processo termina a tarefa para a qual ele foi iniciado, ele termina. O kernel então recupera a memória atribuída para este processo, e para de dar porções de tempo de execução. É dito ao processo pai que seu processo filho que está sendo encerrado, o que permite que um processo aguardar a conclusão de uma tarefa que delegada a um processo filho. Este comportamento é claramente visível nos interpretadores de linha de comando (conhecido como shells). Quando um comando é digitado em um shell, o prompt só volta quando a execução do comando é concluida. A maioria dos shells permitir a execução do comando em segundo plano simplesmente adicionando um &
no final do comando. O prompt é imediatamente exibido em seguida, o que pode ser um problema se o comando deve exibir dados próprios.
Um "daemon" (serviço) é um processo iniciado automaticamente pela sequência de inicialização. Ele continua em execução (em segundo plano) para executar as tarefas de manutenção ou prover serviços a outros processos. Esta "tarefa em segundo plano" é realmente arbitrária e não tem uma importância especial do ponto de vista do sistema. Eles são simplesmente os processos, bastante semelhante a outros processos, que se executam quando está em sua porção de tempo. A distinção é apenas na língua humana: um processo que é executado sem interação com o usuário (em particular, sem qualquer interface gráfica) é dita estar em execução "em segundo plano" ou "como um serviço".
B.5.3. Comunicação Inter Processos
Um processo isolado, seja um daemon ou um aplicativo interativo, raramente é útil por si só, e é por isso que existem vários métodos que permitem a comunicação entre os processos separados, seja para troca de dados ou para controlar um ao outro. O termo genérico que se refere a isso é comunicação entre processos, ou IPC (Inter-Process Communication) para abreviar.
O sistema IPC mais simples é utilizar arquivos. O processo que deseja enviar dados escreve-os em um arquivo (com um nome já conhecido), enquanto o destinatário só precisa abrir o arquivo e ler seu conteúdo.
No caso de que não desejamos armazenar dados em disco, pode-se usar um pipe (conexão), que é simplesmente um objeto com duas extremidades; bytes escritos em uma extremidade são legíveis no outro. Se as extremidades são controladas por processos separados, este se converte em um canal de comunicação entre processos simples e conveniente. Pipes podem ser classificados em duas categorias: pipes nomeados e pipes anônimos. Um pipe nomeado é representado por uma entrada no sistema de arquivos (embora os dados transmitidos não são armazenados lá), para que ambos os processos posam abri-lo de forma independente se a localização do pipe nomeado é conhecido antecipadamente. Nos casos em que os processos de comunicação estão relacionados (por exemplo, um pai e seu processo filho), o processo pai também pode criar um pipe anônimo antes da bifurcação, e o filho o herda. Assim, ambos os processos serão capazes de trocar dados através do pipe sem a necessidade do sistema de arquivos.
No entanto, nem todas as comunicações entre processos são usados para mover os dados. Em muitas situações, a única informação que deve ser transmitida são mensagens de controle tais como "execução em pausa" ou "retomar execução". O Unix (e Linux) fornece um mecanismo conhecido como sinais, através do qual um processo pode simplesmente enviar um sinal (escolhido dentro de uma lista fixa de algumas dezenas de sinais pré-definidos) para outro processo. O único requisito é saber o pid do objetivo.
Para comunicações mais complexas também existem mecanismos que permitem um processo acessar, ou compartilhar, parte da memória alocada para outros processos. Podem utilizar a memória compartilhada entre eles trocar dados.
Finalmente, as conexões de rede também pode ajudar a comunicação de processos; esses processos podem até ser executados em diferentes computadores, possivelmente a milhares de quilômetros de distância.
É bastante normal para um típico sistema similar ao Unix fazer uso de todos esses mecanismos em vários graus.
Bibliotecas de funções desempenham um papel crucial em um sistema operacional similar ao Unix. Eles não são programas propriamente dito, uma vez que não podem ser executados por si próprios, mas coleções de fragmentos de código que podem ser utilizados pelos programas normais. Entre as bibliotecas comuns, você pode encontrar:
a biblioteca padrão C (glibc), que contém as funções básicas como aqueles para abrir arquivos ou conexões de rede, e outras que facilitam as interações com o kernel;
toolkits gráficos, como Gtk+ e o Qt, permitindo que muitos programas reutilizem os objetos gráficos que eles provêm;
a biblioteca libpng que permite carregar, interpretar e salvar imagens no formato PNG.
Graças a essas bibliotecas, as aplicações podem reutilizar o código existente. Seu desenvolvimento é correspondentemente simplificado, em especial quando muitas aplicações reutilizam as mesmas funções. Devido que as bibliotecas são geralmente desenvolvidas por pessoas diferentes, o desenvolvimento global do sistema está mais perto da filosofia histórica do Unix.
Além disso, essas bibliotecas muitas vezes são referidas como "bibliotecas compartilhadas", desde que o kernel possa carregá-las apenas uma vez para a memória, mesmo se vários processos utilizam a mesma biblioteca ao mesmo tempo. Isso permite economia de memória, quando comparado com a situação oposta (hipotética), onde o código para uma biblioteca seria carregada tantas vezes quantos os processos que a utilizam.