C/C++中有没有办法找到当前执行程序的位置(完整路径)?
(
argv[0]
的问题是它没有给出完整路径。)
总结一下:
在具有
/proc
的 Unix 上,真正直接且可靠的方法是:
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)
如果您使用的是 Windows,请使用 GetModuleFileName() 函数。
请注意,以下注释仅适用于 Unix。
这个问题的迂腐答案是,没有“通用”方法可以在所有情况下正确回答这个问题。 正如您所发现的,父进程可以将 argv[0]
设置为任何内容,因此不需要与程序的实际名称或其在文件系统中的位置没有任何关系。
如果
argv[0]
argv[0]
/
,则用getcwd()
确定当前工作目录,然后将argv[0]
附加到它。如果 argv[0]
$PATH
查找 argv[0]
,并将 argv[0]
附加到您在其中找到它的任何目录。
即使假设上面的步骤给了你一个有效的路径名,你仍然可能没有你真正想要的路径名(因为我怀疑你真正想要做的是在某个地方找到一个配置文件)。 硬链接的存在意味着你可能会出现以下情况:
-- 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
作为程序的真实路径。 事实上,它是程序的真正路径,只是不是您想要的路径。 请注意,符号链接不会出现此问题,符号链接在实践中比硬链接更常见。
尽管这种方法原则上不可靠,但它在实践中对于大多数目的来说足够有效。实际上不是答案,只是一个需要记住的注释。
如果您需要可执行位置来发现某些配置或资源文件,也许您应该遵循在系统中放置文件的 Unix 方式:将配置放入
/etc
或
/usr/local/etc
或当前用户主目录中,然后
/usr/share
是放置资源文件的好地方。请记住,在 Unix 系统上,二进制文件自启动以来可能已被删除。它在 Unix 上是完全合法且安全的。上次我检查过 Windows 不允许您删除正在运行的二进制文件。
在许多 POSIX 系统中,您可以检查位于 /proc/PID/exe 下的 simlink。几个例子:
在 Mac OS X 上,使用