简体   繁体   English

C ++如何在Unix中获取正在执行的.so模块的文件名(和路径)

[英]C++ How to get a filename (and path) of the executing .so module in Unix

C++ How to get a filename (and path) of the executing .so module in Unix? C ++如何在Unix中获取正在执行的.so模块的文件名(和路径)?

Something similar to GetModuleFileName on Windows. 与Windows上的GetModuleFileName类似的东西。

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 . 虽然它不是POSIX标准接口,但dladdr()函数可用于许多系统,包括LinuxSolarisDarwin / Mac OS XFreeBSDHP-UXIRIX This function takes an address, which could be a pointer to a static function within the module for example (if cast to void * ), and fills in a Dl_info structure with information including the path name of the shared object containing that address (in the dli_fname member). 该函数接受一个地址,该地址可以是模块中的静态函数的指针(例如,如果转换为void * ),并使用包含该地址的共享对象的路径名的信息填充Dl_info结构(在dli_fname成员)。

Unfortunately, there is no way to do that using UNIX or POSIX. 不幸的是,使用UNIX或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. 如果需要使用它来查找某种数据,则应使用$ PATH环境变量并在与$ 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". 例如,对于某些安装目录“installdir”,在“ installdir / bin”中存储二进制文件并将相关数据存储在某些安装目录和名为“name_of_program”的某个程序的“ installdir / share / 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. 如果是这样的话,那么在看“../share/ name_of_program / name_of_resource_file‘相对于getenv的每个条目(’PATH”)是寻找资源的好办法。 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). 既然你已经说明了你的理由,我建议你简单地使用Qt的QSettings类来获取你的配置信息,因为它使用了每个平台的首选本机机制(Windows上的注册表,Mac OS上的PLIST文件) X,Linux上的Gnome GConf数据库)。 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). 您可能需要查看我的C ++项目模板,因为它使用Qt来做这件事,它提供了简单的命令行选项,可以轻松调整配置设置(“ - prefset”,“ - prefget”和“ - preflist“操纵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. 也就是说,如果您绝对必须使用自己的XML配置文件而不是使用首选的本机机制,我强烈建议您将系统范围的配置放在“ installdir / etc”中,同时将库放在“ installdir / lib”中对于某些安装目录“installdir”,因为这是UNIX系统上配置文件的典型位置,“ installdir / lib”只应用于库文件,而不能用于配置文件和其他勘误表。 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). 我建议您在“$ XDG_CONFIG_HOME”(如果已定义)或“$ HOME / .config”(其中“$ HOME”是用户的主文件夹)中放置用户特定版本的配置文件。

When searching for the system-wide configuration file, I would recommend that you search within $XDG_CONFIG_DIRS if it is defined; 搜索系统范围的配置文件时,我建议您在$ XDG_CONFIG_DIRS内搜索(如果已定义); 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. 如果没有定义,则返回“/ 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“的内容,如果这些文件存在,一旦遇到第一个有效的配置文件就停止搜索将是一种明智的方法。

Credit goes to Roger for pointing out the XDG Basedir Spec and for his excellent constructive criticisms. 感谢Roger指出XDG Basedir Spec以及他出色的建设性批评。

Possible solutions: 可能的解决方案:

  • You can read the /proc/{PID}/mmap file for the list of shared libraries. 您可以阅读/proc/{PID}/mmap文件以获取共享库列表。 Where {PID} is the process pid (you can get it using getpid() ). 其中{PID}是进程pid(您可以使用getpid()获取它)。
  • Call the command line tool ldd for the program binary file (stored in argv[0] ). 为程序二进制文件调用命令行工具ldd (存储在argv[0] )。
  • If you write a solution from scratch take a look of ldd commands source code from uClibc how to get the list of shared libs from an elf binary. 如果您从头开始编写解决方案,请查看来自uClibcldd命令源代码如何从elf二进制文件中获取共享库的列表。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM