Programas típicos do Unix / Linux aceitam as entradas da linha de comandos como um argumento count ( int argc
) e um vetor de argumento ( char *argv[]
). O primeiro elemento de argv
é o nome do programa - seguido pelos argumentos reais.
Por que o nome do programa é passado para o executável como argumento? Existem exemplos de programas usando seu próprio nome (talvez algum tipo de exec
situação)?
command-line
c
arguments
Shrikant Giridhar
fonte
fonte
sh
é o link simbólico paradash
. Eles se comportam diferente, quando chamado comosh
ou comodash
busybox
(comum em discos de resgate e outros), praticamente tudo (cp, mv, rm, ls, ...) é um link simbólico para o busybox.gcc
,bash
,gunzip
, a maior parte do resto do OS ...), como Linux é apenas o kernel.Respostas:
Para começar, observe que esse
argv[0]
não é necessariamente o nome do programa. É o que o chamador fazargv[0]
daexecve
chamada do sistema (por exemplo, veja esta pergunta no Stack Overflow ). (Todas as outras variantes deexec
não são chamadas de sistema, mas interfaces paraexecve
.)Suponha, por exemplo, o seguinte (usando
execl
):/var/tmp/mybackdoor
é o que é executado, masargv[0]
está definido comotop
, e é isso queps
ou (o real)top
exibiria. Veja esta resposta no U&L SE para obter mais informações.Colocando tudo isso de lado: Antes do advento de sistemas de arquivos sofisticados
/proc
,argv[0]
era a única maneira de um processo aprender sobre seu próprio nome. Para que isso seria bom?fonte
bunzip2
,bzcat
ebzip2
, para os quais os dois primeiros são links simbólicos para o terceiro.zcat
não é um link simbólico. Eles parecem evitar as desvantagens dessa técnica usando um script de shell. Mas eles não conseguem imprimir uma--help
saída completa porque alguém que adicionou opções ao gzip também esqueceu de manter o zcat.gunzip
é uma exceção histórica.argv[0]
saída de uso / ajuda em vez de codificar seu nome. Alguns na íntegra, outros apenas o nome da base.Muito:
argv[0]
estásh
. É executado como um shell de login quandoargv[0]
começa com-
.vi
,view
,evim
,eview
,ex
,vimdiff
, etc.shutdown
,reboot
, etc, são ligações simbólicas parasystemctl
.fonte
sendmail
email
. Todo MTA unix vem com um link simbólico para esses dois comandos e é projetado para simular o comportamento do original quando chamado como tal, o que significa que qualquer programa unix que precise enviar e-mail sabe exatamente como pode fazê-lo.test
e[
: quando você chama o primeiro, ele lida com um erro se o último argumento for]
. (no Debian estável atual, esses comandos são dois programas diferentes, mas as versões anteriores e os MacOs ainda usam o mesmo programa). Etex
,latex
e assim por diante: o binário é o mesmo, mas olhando como foi chamado, ele escolhe o bom configuração arquivo.init
É similar.[
considera um erro se o último argumento não for]
.Historicamente,
argv
é apenas uma matriz de ponteiros para as "palavras" da linha de comando; portanto, faz sentido começar com a primeira "palavra", que por acaso é o nome do programa.E existem alguns programas que se comportam de maneira diferente, de acordo com o nome usado para chamá-los, para que você possa criar links diferentes para eles e obter "comandos" diferentes. O exemplo mais extremo que consigo pensar é o busybox , que atua como várias dezenas de "comandos" diferentes, dependendo de como é chamado .
Edit : Referências para a 1ª edição do Unix, conforme solicitado
Pode-se ver, por exemplo, a partir da função principal
cc
dissoargc
eargv
já foram utilizados. O shell copia argumentos paraparbuf
dentro danewarg
parte do loop, enquanto trata o próprio comando da mesma maneira que os argumentos. (Obviamente, mais tarde, ele executa apenas o primeiro argumento, que é o nome do comando). Pareceexecv
e parentes não existiam então.fonte
exec
leva o nome do comando a ser executado e uma matriz de ponteiros de caracteres com terminação zero (melhor visualizada em minnie.tuhs.org/cgi-bin/utree.pl?file=V1/u0.s , ondeexec
leva referências ao rótulo 2 e ao rótulo 1, e no rótulo2:
apareceetc/init\0
, e no rótulo1:
aparece uma referência ao rótulo 2 e um zero final), que é basicamente oexecve
que hoje menosenvp
.execv
eexecl
existiram "para sempre" (ou seja, desde o início até meados da década de 1970) -execv
foi uma chamada do sistema eexecl
uma função da biblioteca que a chamou.execve
não existia então porque o ambiente não existia então. Os outros membros da família foram adicionados mais tarde.execv
a fonte v1 que eu vinculei? Apenas curioso.Casos de uso:
Você pode usar o nome do programa para alterar o comportamento do programa .
Por exemplo, você pode criar alguns links simbólicos para o binário real.
Um exemplo famoso de onde essa técnica é usada é o projeto busybox, que instala apenas um único binário e muitos links simbólicos. (LS, CP, MV, etc). Eles estão fazendo isso para economizar espaço de armazenamento porque seus destinos são pequenos dispositivos incorporados.
Isso também é usado no
setarch
util-linux:Aqui eles estão usando essa técnica basicamente para evitar muitos arquivos de origem duplicados ou apenas para manter as fontes mais legíveis.
Outro caso de uso seria um programa que precisa carregar alguns módulos ou dados em tempo de execução. Ter o caminho do programa permite carregar módulos a partir de um caminho relativo ao local do programa .
Além disso, muitos programas imprimem mensagens de erro, incluindo o nome do programa .
Porquê :
man 3p execve
):Observe que o padrão C indica "nome do programa" e não "nome do arquivo".
fonte
Além de programas que alteram seu comportamento, dependendo de como eles foram chamados, acho
argv[0]
útil imprimir o uso de um programa, da seguinte forma:Isso faz com que a mensagem de uso sempre use o nome pelo qual foi chamada. Se o programa for renomeado, sua mensagem de uso será alterada. Inclusive inclui o nome do caminho com o qual foi chamado:
É um toque agradável, especialmente para pequenas ferramentas / scripts para fins especiais que podem estar espalhados por todo o lugar.
Isso parece prática comum também nas ferramentas GNU, veja,
ls
por exemplo:fonte
A pessoa executa a digitação programa:
program_name0 arg1 arg2 arg3 ...
.Portanto, o shell já deve dividir o token, e o primeiro token já é o nome do programa. E BTW, para que haja os mesmos índices no lado do programa e no shell.
Acho que esse foi apenas um truque de conveniência (no começo) e, como você vê em outras respostas, também foi muito útil, portanto, essa tradição foi continuada e definida como API.
fonte
Basicamente, argv inclui o nome do programa para que você possa escrever mensagens de erro como
prgm: file: No such file or directory
, que seriam implementadas com algo como isto:fonte
Outro exemplo de aplicação disso é este programa, que se substitui por ... próprio, até você digitar algo que não é
y
.Obviamente, é um exemplo artificial, se interessante, mas acho que isso pode ter usos reais - por exemplo, um binário auto-atualizável, que reescreve seu próprio espaço de memória com uma nova versão de si mesma que foi baixada ou alterada.
Exemplo:
Fonte e mais algumas informações .
fonte
O caminho para o programa é
argv[0]
, para que o programa possa recuperar arquivos de configuração etc. do diretório de instalação.Isso seria impossível sem
argv[0]
.fonte
(char *path_to_program, char **argv, int argc)
por exemplo~/.<program>
,/etc/<program
,$XDG_CONFIG_HOME
) e tomar um parâmetro para alterá-lo ou ter uma opção de tempo de compilação que coze em uma constante para o binário.O ccache se comporta dessa maneira para imitar diferentes chamadas aos binários do compilador. O ccache é um cache de compilação - o objetivo principal nunca é compilar o mesmo código fonte duas vezes, mas retornar o código do objeto do cache, se possível.
Na página de manual do ccache , "existem duas maneiras de usar o ccache. Você pode prefixar seus comandos de compilação com o ccache ou pode deixar o ccache se disfarçar como compilador criando um link simbólico (chamado de compilador) para o ccache. é mais conveniente se você quiser experimentar o ccache ou desejar usá-lo em alguns projetos específicos. O segundo método é mais útil quando você deseja usar o ccache para todas as suas compilações. "
O método symlinks envolve a execução destes comandos:
... o efeito é permitir ao ccache capturar todos os comandos que seriam enviados aos compiladores, permitindo que o ccache retorne um arquivo em cache ou transmita o comando ao compilador real.
fonte