Linux 如何在 C 中找到可执行文件的位置?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/933850/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-03 17:21:40  来源:igfitidea点击:

How do I find the location of the executable in C?

c++clinuxunixpath

提问by eran

Is there a way in C/C++ to find the location (full path) of the current executed program?

C/C++ 中有没有办法找到当前执行程序的位置(完整路径)?

(The problem with argv[0]is that it does not give the full path.)

(问题argv[0]在于它没有给出完整路径。)

采纳答案by lispmachine

To summarize:

总结一下:

  • On Unixes with /procreally straight and realiable way is to:

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

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

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

  • On Unixes without /proc(i.e. if above fails):

    • If argv[0] starts with "/" (absolute path) this is the path.

    • Otherwise if argv[0] contains "/" (relative path) append it to cwd (assuming it hasn't been changed yet).

    • Otherwise search directories in $PATHfor executable argv[0].

    Afterwards it may be reasonable to check whether the executable isn't actually a symlink. If it is resolve it relative to the symlink directory.

    This step is not necessary in /proc method (at least for Linux). There the proc symlink points directly to executable.

    Note that it is up to the calling process to set argv[0]correctly. It is right most of the times however there are occasions when the calling process cannot be trusted (ex. setuid executable).

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

  • 在 Unix 上,/proc真正直接且可行的方法是:

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

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

    • readlink("/proc/self/path/a.out", buf, bufsize)(索拉里斯)

  • 在没有的 Unix 上/proc(即如果上述失败):

    • 如果 argv[0] 以“/”(绝对路径)开头,这就是路径。

    • 否则,如果 argv[0] 包含“/”(相对路径),则将其附加到 cwd(假设尚未更改)。

    • 否则在目录中搜索$PATH可执行文件argv[0]

    之后检查可执行文件是否实际上不是符号链接可能是合理的。如果是相对于符号链接目录解析它。

    这一步在 /proc 方法中不是必需的(至少对于 Linux)。proc 符号链接直接指向可执行文件。

    请注意,argv[0]正确设置取决于调用过程。大多数情况下是正确的,但有时调用进程是不可信的(例如 setuid 可执行文件)。

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

回答by eran

In many POSIX systems you could check a simlink located under /proc/PID/exe. Few examples:

在许多 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

回答by Shino C G

Use GetModuleFileName()function if you are using Windows.

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

回答by Dale Hagglund

Please note that the following comments are unix-only.

请注意,以下注释仅适用于 unix。

The pedantic answer to this question is that there is no generalway to answer this question correctly in all cases. As you've discovered, argv[0] can be set to anything at all by the parent process, and so need have no relation whatsoever to the actual name of the program or its location in the file system.

对这个问题的迂腐回答是,没有在所有情况下都正确回答这个问题的通用方法。正如您所发现的,父进程可以将 argv[0] 设置为任何内容,因此与程序的实际名称或其在文件系统中的位置没有任何关系。

However, the following heuristic often works:

但是,以下启发式方法通常有效:

  1. If argv[0] is an absolute path, assume this is the full path to the executable.
  2. If argv[0] is a relative path, ie, it contains a /, determine the current working directory with getcwd() and then append argv[0] to it.
  3. If argv[0] is a plain word, search $PATH looking for argv[0], and append argv[0] to whatever directory you find it in.
  1. 如果 argv[0] 是绝对路径,则假定这是可执行文件的完整路径。
  2. 如果 argv[0] 是一个相对路径,即它包含一个/,请使用 getcwd() 确定当前工作目录,然后将 argv[0] 附加到它。
  3. 如果 argv[0] 是一个简单的词,则在 $PATH 中搜索 argv[0],并将 argv[0] 附加到您找到它的任何目录中。

Note that all of these can be circumvented by the process which invoked the program in question. Finally, you can use linux-specific techniques, such as mentioned by emg-2. There are probably equivalent techniques on other operating systems.

请注意,所有这些都可以通过调用相关程序的进程来规避。最后,您可以使用特定于 linux 的技术,例如 emg-2 中提到的。在其他操作系统上可能有等效的技术。

Even supposing that the steps above give you a valid path name, you still might not have the path name you actually want (since I suspect that what you actually want to do is find a configuration file somewhere). The presence of hard links means that you can have the following situation:

即使假设上述步骤为您提供了一个有效的路径名,您仍然可能没有您真正想要的路径名(因为我怀疑您实际上想要做的是在某处找到一个配置文件)。硬链接的存在意味着您可能会遇到以下情况:

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

Now, the approach above (including, I suspect, /proc/$pid/exe) will give /some/where/else/fooas the real path to the program. And, in fact, it is areal path to the program, just not the one you wanted. Note that this problem doesn't occur with symbolic links which are much more common in practice than hard links.

现在,上面的方法(包括,我怀疑,/proc/$pid/exe)将/some/where/else/foo作为程序的真实路径。而且,事实上,这是通往程序真正途径,只是不是您想要的途径。请注意,符号链接不会发生此问题,符号链接在实践中比硬链接更常见。

In spite of the fact that this approach is in principle unreliable, it works well enough in practice for most purposes.

尽管这种方法原则上不可靠,但它在实践中对于大多数目的来说效果很好。

回答by Thomas

Remember that on Unix systems the binary may have been removed since it was started. It's perfectly legal and safe on Unix. Last I checked Windows will not allow you to remove a running binary.

请记住,在 Unix 系统上,二进制文件可能自启动以来已被删除。它在 Unix 上是完全合法和安全的。最后我检查了 Windows 不允许您删除正在运行的二进制文件。

/proc/self/exe will still be readable, but it will not be a working symlink really. It will be... odd.

/proc/self/exe 仍然是可读的,但它实际上不会是一个有效的符号链接。这会……很奇怪。

回答by Michael

Not an answer actually, but just a note to keep in mind.

实际上不是答案,而只是要记住的注释。

As we could see, the problem of finding the location of running executable is quite tricky and platform-specific in Linux and Unix. One should think twice before doing that.

正如我们所见,在 Linux 和 Unix 中找到运行可执行文件的位置的问题非常棘手且特定于平台。在这样做之前,应该三思而后行。

If you need your executable location for discovering some configuration or resource files, maybe you should follow the Unix way of placing files in the system: put configs to /etcor /usr/local/etcor in current user home directory, and /usr/shareis a good place to put your resource files.

如果你需要你的可执行位置来发现一些配置或资源文件,也许你应该遵循 Unix 在系统中放置文件的方式:将 configs 放在/etc/usr/local/etc或在当前用户主目录中,这/usr/share是一个放置资源文件的好地方。

回答by JCCyC

I would

我会

1) Use the basename() function: http://linux.die.net/man/3/basename
2) chdir() to that directory
3) Use getpwd() to get the current directory

1) 使用 basename() 函数:http: //linux.die.net/man/3/basename
2) chdir() 到该目录
3) 使用 getpwd() 获取当前目录

That way you'll get the directory in a neat, full form, instead of ./ or ../bin/.

这样,您将以整洁、完整的形式获得目录,而不是 ./ 或 ../bin/。

Maybe you'll want to save and restore the current directory, if that is important for your program.

如果这对您的程序很重要,您可能想要保存和恢复当前目录。

回答by Grumbel

For Linux you can find the /proc/self/exeway of doing things bundled up in a nice library called binreloc, you can find the library at:

对于 Linux,您可以/proc/self/exe在一个名为 binreloc 的库中找到捆绑的处理方式,您可以在以下位置找到该库:

回答by Tim Ruddick

On Mac OS X, use _NSGetExecutablePath.

在 Mac OS X 上,使用_NSGetExecutablePath.

See man 3 dyldand this answerto a similar question.

请参阅man 3 dyld对类似问题的回答。