c++ - create - linux c system()




Como faço para encontrar a localização do executável em C? (6)

Esta questão já tem uma resposta aqui:

Existe uma maneira em C / C ++ para encontrar o local (caminho completo) do programa executado atual?

(O problema com argv[0] é que ele não fornece o caminho completo).


Em muitos sistemas POSIX você pode verificar um simlink localizado em / proc / PID / exe. Alguns exemplos:

# file /proc/*/exe
/proc/1001/exe: symbolic link to /usr/bin/distccd
/proc/1023/exe: symbolic link to /usr/sbin/sendmail.sendmail
/proc/1043/exe: symbolic link to /usr/sbin/crond

Eu gostaria

1) Use a função basename (): http://linux.die.net/man/3/basename
2) chdir () para esse diretório
3) Use getpwd () para obter o diretório atual

Dessa forma, você obterá o diretório em uma forma completa, em vez de ./ ou ../bin/.

Talvez você queira salvar e restaurar o diretório atual, se isso for importante para o seu programa.


Não uma resposta, na verdade, mas apenas uma nota para ter em mente.

Como pudemos ver, o problema de encontrar a localização do executável em execução é bastante complicado e específico da plataforma no Linux e no Unix. Deve-se pensar duas vezes antes de fazer isso.

Se você precisa de sua localização executável para descobrir alguns arquivos de configuração ou recursos, talvez você deva seguir a maneira Unix de colocar arquivos no sistema: coloque configs em /etc ou /usr/local/etc ou no diretório home do usuário atual, e /usr/share é um bom lugar para colocar seus arquivos de recursos.



Para resumir:

  • Em Unixes com /proc realmente direto e de maneira realiable é:

    • readlink("/proc/self/exe", buf, bufsize) (Linux)

    • readlink("/proc/curproc/file", buf, bufsize) (FreeBSD)

    • readlink("/proc/self/path/a.out", buf, bufsize) (Solaris)

  • Em Unixes sem /proc (ou seja, se acima falhar):

    • Se argv [0] começar com "/" (caminho absoluto), este é o caminho.

    • Caso contrário, se argv [0] contiver "/" (caminho relativo) anexá-lo a cwd (assumindo que ainda não foi alterado).

    • Caso contrário, procure diretórios em $PATH para o executável argv[0] .

    Depois disso, pode ser razoável verificar se o executável não é realmente um link simbólico. Se for resolvido em relação ao diretório do symlink.

    Esta etapa não é necessária no método / proc (pelo menos para o Linux). Lá, o link simbólico proc aponta diretamente para o executável.

    Observe que cabe ao processo de chamada definir argv[0] corretamente. É certo na maioria das vezes no entanto, há ocasiões em que o processo de chamada não pode ser confiável (ex. Setuid executável).

  • No Windows: use GetModuleFileName(NULL, buf, bufsize)


Por favor, note que os comentários a seguir são unix-only.

A resposta pedante para essa pergunta é que não há uma maneira geral de responder a essa pergunta corretamente em todos os casos. Como você descobriu, o argv [0] pode ser configurado para qualquer coisa pelo processo pai e, portanto, não precisa ter nenhuma relação com o nome real do programa ou sua localização no sistema de arquivos.

No entanto, a seguinte heurística geralmente funciona:

  1. Se argv [0] for um caminho absoluto, assuma que este é o caminho completo para o executável.
  2. Se argv [0] é um caminho relativo, isto é, contém um / , determina o diretório de trabalho atual com getcwd () e depois adiciona argv [0] a ele.
  3. Se argv [0] for uma palavra simples, pesquise $ PATH procurando por argv [0] e acrescente argv [0] ao diretório em que você o encontrar.

Note que tudo isso pode ser contornado pelo processo que invocou o programa em questão. Finalmente, você pode usar técnicas específicas do Linux, como mencionado por emg-2. Existem provavelmente técnicas equivalentes em outros sistemas operacionais.

Mesmo supondo que as etapas acima forneçam um nome de caminho válido, você ainda pode não ter o nome do caminho que realmente deseja (já que suspeito que o que você realmente quer fazer é encontrar um arquivo de configuração em algum lugar). A presença de links físicos significa que você pode ter a seguinte situação:

-- assume /app/bin/foo is the actual program
$ mkdir /some/where/else
$ ln /app/bin/foo /some/where/else/foo     # create a hard link to foo
$ /some/where/else/foo

Agora, a abordagem acima (incluindo, eu suspeito, / proc / $ pid / exe) dará /some/where/else/foo como o caminho real para o programa. E, de fato, é um caminho real para o programa, mas não o que você queria. Observe que esse problema não ocorre com links simbólicos que são muito mais comuns na prática do que links rígidos.

Apesar do fato de que essa abordagem não é, em princípio, confiável, ela funciona bem o suficiente na prática para a maioria dos propósitos.





path