Estou tentando entender os conceitos de shell e terminal e a relação exata entre eles do aspecto dos processos do sistema operacional. Então, eu tenho algumas perguntas nesse campo.
Verificação de sanidade: Pelo que entendi, o shell é a interface através da qual o usuário pode interagir com o SO, ou seja: executar outros processos. Embora o shell (por exemplo, Bash) seja apenas outro processo. Isso está certo?
Existe uma maneira de executar um processo que não seja filho de um processo de shell?
Variáveis de ambiente: No bash, existem vários scripts que são executados quando você gera um shell, por exemplo
.bashrc
,.bash_profile
, etc. (depende do tipo de shell - interativo versus não interativo, login versus não login). Esses scripts definem as variáveis de ambiente. Se houver uma maneira de executar um processo independentemente de qualquer shell, de onde vêm as variáveis de ambiente?
Sim, mas um "shell" é especificamente uma interface de usuário , não uma interface de programação. Outros programas não precisam interagir com ele – eles podem usar diretamente as mesmas chamadas de sistema para criar novos processos.
Portanto, o shell de linha de comando está no mesmo nível de outros programas, por exemplo, gerenciadores de serviço ou interfaces gráficas de usuário (shells gráficos).
Sim. Em sistemas do tipo Unix, é um processo completamente normal e sem privilégios.
Do ponto de vista do usuário: sim, existem várias maneiras.
A maioria dos shells tem uma palavra-
exec
chave que faz com que o novo programa substitua o shell (mantendo o mesmo PID e parentesco), o que provavelmente não é o que você quis dizer, mas tecnicamente o que você pediu.As sessões gráficas da área de trabalho geralmente iniciam sem invocar o bash ou qualquer outro shell, e isso se aplica automaticamente aos aplicativos iniciados por meio dos menus gráficos. O pai do aplicativo será qualquer processo responsável por mostrar o menu (por exemplo, o gerenciador de janelas ou o painel).
O sistema systemd init atualmente popular não usa shell ao iniciar serviços, então você pode definir um .service e iniciá-lo – o pai do serviço será o próprio init. Ele também possui um recurso que permite que serviços temporários sejam criados dinamicamente usando
systemd-run
, com os mesmos resultados.Do ponto de vista de um programador, basta usar as chamadas de sistema
fork()
eexecve()
para iniciar um novo processo. (Existem detalhes específicos do SO, por exemplo, fork() pode de fato ser um wrapper para uma chamada diferente, mas ainda funciona da mesma maneira.)De fato, mesmo se o programa quisesse invocar um shell, ele o faria criando um novo processo filho e executando /bin/sh usando o mesmo fork+exec. Não há nenhuma chamada de sistema especial para executar um shell. (O programador pode usar, por exemplo, system() ao escrever em C, ou os.system() em Python, mas esses ainda são apenas wrappers de conveniência em torno de fork/exec.)
Bem, às vezes não. (É um problema prático real ao tentar fazer com que aplicativos gráficos peguem personalizações de ambiente, dependendo de como esse ambiente gráfico específico é iniciado.)
No geral, porém, as variáveis de ambiente não são exclusivas dos shells da CLI. Cada processo, não importa como foi iniciado (incluindo até mesmo o processo init), recebe um array de strings contendo sua linha de comando – e um array de strings contendo suas variáveis de ambiente. Ao iniciar um processo filho, ele pode especificar um ambiente diferente ou permitir que uma cópia de seu próprio ambiente seja herdada.
Então, quando você faz login, seu shell já recebe algumas variáveis de ambiente iniciais de seu pai. Esses scripts de inicialização (bashrc, etc.) são apenas um local conveniente para um usuário personalizar as variáveis de ambiente que os processos filho do shell herdarão.
Muitas partes desta resposta também se aplicam totalmente ao Windows - embora sua interface gráfica seja um pouco mais complexa, os shells da CLI (cmd.exe e PowerShell) ainda são programas comuns que não são usados em operação normal. A única grande diferença é que o Windows tem uma única chamada "CreateProcess" em vez das chamadas "fork + exec" separadas no estilo Unix.
Está correto. Em última análise, o shell executará a
exec
chamada do sistema, que está disponível em todos os sistemas operacionais compatíveis com POSIX e, mais geralmente, em todos os sistemas operacionais do tipo Unix, incluindo o Linux. Outros sistemas operacionais têm conceitos semelhantes. No Linux, a chamada doexec
sistema, em última análise, chamará aexecve
função, que é fornecida pelo kernel e faz o trabalho real de carregar o arquivo executável e executá-lo.Sim. Qualquer processo pode chamar
exec
, e não precisa ser um "shell". Por exemplo, quando você inicia um programa clicando em um navegador de sistema de arquivos, o software de desktop é aquele que executa aexec
chamada, não há shell. Observe que o processo se torna filho do software de desktop que o iniciou. Todos os processos são filhos de um outro processo, exceto o primeiro, que é chamadoinit
e tem PID 1. Ele é responsável por configurar o sistema operacional na inicialização e iniciar todos os outros processos, como serviços em segundo plano e login na área de trabalho. No Linux hoje em dia,systemd
é frequentemente usado comoinit
processo, mas existem outras alternativas.Existem diversas variantes de
exec
(execl
,execle
, ...) que possuem vários argumentos além do nome do programa a ser executado. Em última análise, aexecve
chamada do sistema recebe um nome de programa, uma lista de strings que são os argumentos da linha de comando e uma lista de strings que são as variáveis de ambiente. Por exemplo, ao iniciar o software a partir de um navegador do sistema de arquivos, as variáveis de ambiente podem ser copiadas das variáveis do próprio navegador do sistema de arquivos, possivelmente modificadas pelo navegador do sistema de arquivos. Isso depende inteiramente dos programadores do navegador do sistema de arquivos.Algumas leituras adicionais: