C++如何在 Unix 中获取正在执行的 .so 模块的文件名(和路径)
C++ 如何获取 Unix 中正在执行的 .so 模块的文件名(和路径)?
类似于 Windows 上的 GetModuleFileName。
C++ How to get a filename (and path) of the executing .so module in Unix?
Something similar to GetModuleFileName on Windows.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
尽管它不是 POSIX 标准接口,但
dladdr()
函数在许多系统上都可用,包括 Linux, Solaris、达尔文/Mac OS X、FreeBSD、HP-UX,以及IRIX。该函数采用一个地址,例如,该地址可以是指向模块内静态函数的指针(如果转换为void *
),并用信息填充Dl_info
结构包括包含该地址的共享对象的路径名(在 dli_fname 成员中)。Although it is not a POSIX standard interface, the
dladdr()
function is available on many systems including Linux, Solaris, Darwin/Mac OS X, FreeBSD, HP-UX, and IRIX. This function takes an address, which could be a pointer to a static function within the module for example (if cast tovoid *
), and fills in aDl_info
structure with information including the path name of the shared object containing that address (in thedli_fname
member).不幸的是,使用 UNIX 或 POSIX 无法做到这一点。如果需要使用它来查找某种数据,则应该使用 $PATH 环境变量并在与 $PATH 中每个条目相关的路径中搜索数据。例如,将某些安装目录“installdir”的二进制文件存储在“installdir/bin”中并将相关数据存储在“installdir/share/<”中并不罕见。 i>name_of_program”,用于某些安装目录和名为“name_of_program”的程序。如果是这种情况,那么查看相对于 getenv("PATH") 中每个条目的“../share/name_of_program/name_of_resource_file”是一种很好的搜索方法为了资源。您可以做的另一件事是允许在命令行或某些配置文件中提供必要的信息,并且仅在需要时才执行搜索作为后备选项。
编辑
既然您已经说明了这样做的理由,我建议您只需使用 QSettings 类用于获取配置信息,因为它使用每个平台的首选本机机制(Windows 上的注册表、Mac OS X 上的 PLIST 文件、Linux 上的 Gnome GConf 数据库)。您可能需要查看我的 C++ 项目模板,因为它使用了Qt 就是为了做到这一点,它提供了简单的命令行选项来轻松调整配置设置(“--prefset”、“--prefget”和“--preflist”操作 QSettings)。
也就是说,如果您绝对必须使用自己的 XML 配置文件而不是使用首选的本机机制,我强烈建议您将系统范围的配置放在“installdir/etc”中,同时将您的对于某些安装目录“installdir”,“installdir/lib”中的库,因为这是 UNIX 系统上配置文件的典型位置,并且“installdir/lib”应该仅用于库文件,而不是配置文件和其他勘误表。我建议您将配置文件的用户特定版本放在“$XDG_CONFIG_HOME”(如果已定义)或“$HOME/.config”(其中“$HOME”是用户的主文件夹)中。
当搜索系统范围的配置文件时,我建议您在 $XDG_CONFIG_DIRS 中搜索(如果已定义);如果未定义,则返回到“/etc/xdg”或搜索相对于“$PATH”的“../etc/name_of_your_program.conf.xml”,也可能相对于“$LD_LIBRARY_PATH”,“ $DYLD_LIBRARY_PATH", "$DYLD_FALLBACK_LIBRARY_PATH"),“/etc/ld.so.conf”的内容(如果存在)以及“/etc/ld.so.conf.d/*.conf”的内容(如果这些文件存在)存在,一旦遇到第一个有效的此类配置文件就停止搜索将是一个明智的方法。
感谢 Roger 指出 XDG Basedir Spec 以及他出色的建设性批评。
Unfortunately, there is no way to do that using UNIX or POSIX. If you need to use it to look up some sort of data, you should use the $PATH environment variable and search for the data in a path that is relative to each entry in $PATH. For example, it is not uncommon to store binaries in "installdir/bin" for some installation directory "installdir" and to store the associated data in "installdir/share/name_of_program" for some installation directory and some program named "name_of_program". If that is the case, then looking at "../share/name_of_program/name_of_resource_file" relative to each entry in getenv("PATH") is a good way of searching for resources. Another thing you could do is allow the necessary information to be provided on the commandline or in some configuration file, and only perform the search if needed as a fallback option.
Edit
Now that you've stated your rationale for this, I would advise you to simply use the QSettings class from Qt for your configuration information, as it uses the preferred native mechanism for each platform (the registry on Windows, a PLIST file on Mac OS X, the Gnome GConf database on Linux). You may want to take a look at my C++ Project Template as it uses Qt to do just this, and it provides simple commandline options to easily tweak the configuration settings ("--prefset", "--prefget", and "--preflist" manipulate QSettings).
That said, if you absolutely must use an XML configuration file of your own instead of using the preferred native mechanism, I strongly advise you to place the system-wide configuration in "installdir/etc" while placing your library in "installdir/lib" for some installation directory "installdir", as that is the typical place for configuration files on UNIX systems, and "installdir/lib" should ONLY be used for library files, not for configuration files and other errata. I suggest you place a user-specific version of the configuration file in "$XDG_CONFIG_HOME" (if it is defined) or in "$HOME/.config" (where "$HOME" is the user's home folder).
When searching for the system-wide configuration file, I would recommend that you search within $XDG_CONFIG_DIRS if it is defined; if it isn't defined, then falling back to "/etc/xdg" or searching for "../etc/name_of_your_program.conf.xml" relative to "$PATH" and possibly also relative to the "$LD_LIBRARY_PATH", "$DYLD_LIBRARY_PATH", "$DYLD_FALLBACK_LIBRARY_PATH"), the contents of "/etc/ld.so.conf" if it exists, and the contents of "/etc/ld.so.conf.d/*.conf" if those files exist, halting your search as soon as you encounter the first valid such configuration file would be a sensible approach.
Credit goes to Roger for pointing out the XDG Basedir Spec and for his excellent constructive criticisms.
可能的解决方案:
/proc/{PID}/mmap
文件中的共享库列表。其中 {PID} 是进程 pid(您可以使用 getpid() 获取它)。argv[0]
中)调用命令行工具ldd
。Possible solutions:
/proc/{PID}/mmap
file for the list of shared libraries. Where {PID} is the process pid (you can get it usinggetpid()
).ldd
for the program binary file (stored inargv[0]
).ldd
commands source code fromuClibc
how to get the list of shared libs from an elf binary.