如何在C中找到可执行文件的位置?[副本]

nom7f22z  于 2023-06-21  发布在  其他
关注(0)|答案(9)|浏览(80)

此问题已在此处有答案

Finding current executable's path without /proc/self/exe(15个回答)
7年前关闭。
C/C++中有没有一种方法可以找到当前执行程序的位置(完整路径)?
(The argv[0]的问题是它没有给予完整的路径。

wpx232ag

wpx232ag1#

总结如下:

  • 在Unix上用/proc真正直接和可靠的方法是:
  • readlink("/proc/self/exe", buf, bufsize)(Linux)
  • readlink("/proc/curproc/file", buf, bufsize)(FreeBSD)
  • readlink("/proc/self/path/a.out", buf, bufsize)(Solaris)
  • 在没有/proc的Unix上(即如果上述失败):
  • 如果argv[0]以“/”(绝对路径)开头,这就是路径。
  • 否则,如果argv[0]包含“/”(相对路径),则将其附加到cwd(假设它尚未更改)。
  • 否则,在$PATH中搜索可执行文件argv[0]的目录。

之后,检查可执行文件是否实际上不是符号链接可能是合理的。如果是,则相对于符号链接目录解析它。
这一步在/proc方法中不是必需的(至少对于Linux是这样)。proc符号链接直接指向可执行文件。
请注意,正确设置argv[0]取决于调用进程。在大多数情况下,这是正确的,但是有时候调用进程不能被信任(例如:setuid可执行文件)。

  • 在Windows上:使用GetModuleFileName(NULL, buf, bufsize)
lfapxunr

lfapxunr2#

如果您使用的是Windows,请使用GetModuleFileName()函数。

hl0ma9xz

hl0ma9xz3#

请注意,下面的注解仅适用于unix。
对这个问题的迂腐的回答是,在所有情况下都没有一种通用的方法来正确回答这个问题。正如您所发现的,argv [0]可以被父进程设置为任何值,因此不需要与程序的实际名称或其在文件系统中的位置有任何关系。
然而,以下启发式通常有效:
1.如果argv [0]是绝对路径,则假定这是可执行文件的完整路径。
1.如果argv [0]是一个相对路径,即它包含一个/,使用getcwd()确定当前工作目录,然后将argv [0]附加到它。
1.如果argv [0]是一个普通单词,搜索$PATH查找argv [0],并将argv [0]附加到您找到它的任何目录中。
请注意,所有这些都可以通过调用相关程序的进程来规避。最后,您可以使用特定于Linux的技术,例如emg-2中提到的技术。在其他操作系统上可能有等效的技术。
即使假设上面的步骤给了你一个有效的路径名,你仍然可能没有你实际想要的路径名(因为我怀疑你实际想要做的是在某处找到一个配置文件)。硬链接的存在意味着您可能会遇到以下情况:

-- 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

现在,上面的方法(我怀疑包括/proc/$pid/exe)将给出/some/where/else/foo作为程序的真实路径。而且,事实上,这是一个真正的程序路径,只是不是你想要的。请注意,符号链接不会出现这个问题,符号链接在实践中比硬链接更常见。
尽管这种方法在原则上不可靠,但在实践中对大多数目的来说都足够有效。

toe95027

toe950274#

实际上不是答案,只是一个要记住的注解。
正如我们所看到的,在Linux和Unix中查找运行可执行文件的位置是相当棘手的,而且是平台特定的。在做那件事之前应该三思而后行。
如果你需要你的可执行文件位置来发现一些配置或资源文件,也许你应该遵循Unix在系统中放置文件的方式:将配置文件放到/etc/usr/local/etc或当前用户的主目录中,/usr/share是放置资源文件的好地方。

vsnjm48y

vsnjm48y5#

在许多POSIX系统中,您可以检查位于/proc/PID/exe下的simlink。几个例子:

# 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
kx5bkwkv

kx5bkwkv6#

请记住,在Unix系统上,二进制文件可能在启动后就被删除了。它在Unix上是完全法律的和安全的。最后我检查了Windows将不允许您删除正在运行的二进制文件。
/proc/self/exe仍然是可读的,但它实际上不是一个有效的符号链接。会是...奇怪。

83qze16e

83qze16e7#

在Mac OS X上,使用_NSGetExecutablePath
参见man 3 dyldthis answer来回答类似的问题。

2hh7jdfx

2hh7jdfx8#

对于Linux,你可以在一个名为binreloc的漂亮库中找到/proc/self/exe的工作方式,你可以在以下位置找到这个库:

e4yzc0pl

e4yzc0pl9#

我会的
1.使用dirname()函数:http://linux.die.net/man/3/dirname

  1. chdir()到该目录
    1.使用getcwd()获取当前目录
    这样,您将以整洁完整的形式获得目录,而不是./或../bin/。
    如果保存和恢复当前目录对程序很重要,那么可能需要保存和恢复当前目录。

相关问题