I understand that a process can change its own name, but why isn't the name the same in both cases?
Porque os programas envolvidos não estão mudando seus próprios nomes. Eles recebem os nomes que o comportamento padrão do Linux atribui. (Outros sistemas operacionais se comportam de maneira diferente, mas essa é uma questão do Linux porque fala sobre /proc/*/comm
arquivos.)
No Linux, o nome do programa em comm
é obtido de qualquer nome do arquivo de imagem do programa passado para execve()
. Note que este não é nem o vetor argumento nem o vetor ambiente, e a declaração de que este nome é retirado do vetor argumento no Linux é errônea.
Os nomes dos arquivos de imagem do programa que o shell está realmente passando são /usr/bin/python
e /usr/bin/mirage
, então python
e mirage
são para os quais /proc/self/comm
foram inicializados. ( comm
é o nome da base do nome do arquivo da imagem do programa, truncado / preenchido).
O vetor argumento inicializa o que um processo tem em /proc/self/cmdline
e o vetor ambiente inicializa o que tem em /proc/self/environ
. Então, com estes e /proc/self/comm
, e presumindo que um programa não os altere quando executado, você conhece todas as três informações que foram passadas para execve()
e, portanto, exatamente como um processo foi originalmente lançado (embora Estritamente falando, é assim que o programa foi lançado, pois o processo foi lançado com fork()
).
Aqui está um exemplo dessas três partes em ação, usando clearenv
, setenv
e exec
do conjunto de ferramentas para configurar um ambiente pequeno e forçar argv[0]
para fins de exposição:
% clearenv setenv 1THIS 'is the environment string' setenv 2COMPRISING 'all of the environment.' \ > exec -a 'This is argv[0].' /bin/sleep 100 & [1] 15564 % for i in /proc/$\!/{comm,cmdline,environ} ; do printf "%s:" $i ; cat -v $i ; printf "\n" ; done /proc/15564/comm:3 /proc/15564/cmdline:This is argv[0].^@100^@ /proc/15564/environ:1THIS=is the environment string^@2COMPRISING=all of the environment.^@ %
E, de fato, esses são exatamente o que o comando exec
do conjunto de ferramentas de nos passou para execve()
para executar /bin/sleep
. (O 3
é porque exec
usa a função fexecve()
da biblioteca C, que usa internamente nomes de arquivos de imagens de programas no formato /proc/self/fd/3
.)
O arquivo de imagem do programa que passa a ser um script com um intérprete nomeado e o número mágico #!
, causando a substituição desse interpretador pelo arquivo de imagem do programa e o deslocamento do vetor argumento, não muda o que entra em comm
. Permanece como qualquer nome de arquivo de imagem do programa originalmente dado a execve()
. Sim, o Linux é inconsistente aqui, porque faz alterar o que entra em cmdline
em tais casos para ser a sequência de argumentos final efetiva.