C++ 如何使用dlopen()获取可执行文件路径

C++ 如何使用dlopen()获取可执行文件路径,c++,c,filepath,dlopen,C++,C,Filepath,Dlopen,我正在尝试使用dlopen()和dlinfo()获取可执行文件的路径。通过使用dlopen()返回的句柄,我能够获取到.so的路径,但是当我使用dlopen返回的句柄时(NULL,RTLD_-LAZY);那我回去的路是空的 void* executable_handle = dlopen(0, RTLD_LAZY); if (nullptr != executable_handle) { char pp_linkmap[sizeof(link_map)]; int r = dl

我正在尝试使用dlopen()和dlinfo()获取可执行文件的路径。通过使用dlopen()返回的句柄,我能够获取到.so的路径,但是当我使用dlopen返回的句柄时(NULL,RTLD_-LAZY);那我回去的路是空的

void* executable_handle = dlopen(0, RTLD_LAZY);
if (nullptr != executable_handle) 
{
    char pp_linkmap[sizeof(link_map)];
    int r = dlinfo(executable_handle, RTLD_DI_LINKMAP, pp_linkmap);
    if (0 == r)
    {
        link_map* plink = *(link_map**)pp_linkmap;
        printf("path: %s\n", plink->l_name);
    }
}
我认为可执行文件的句柄可以在dlinfo函数中以与a.so句柄相同的方式使用,这是错误的吗

我认为可执行文件的句柄可以在dlinfo函数中以与a.so句柄相同的方式使用,这是错误的吗

是的,你是

动态链接器不知道主可执行文件是从哪个文件加载的。这是因为内核对主可执行文件执行所有
mmap
s,并且只将文件描述符传递给动态加载程序(动态加载程序的任务是加载其他所需的库并启动可执行文件的运行)

我试图在linux上复制GetModuleFileName()的一些功能

没有可靠的方法可以做到这一点。事实上,可执行文件可能根本不存在于磁盘上的任何地方——在程序仍在运行时运行可执行文件并删除可执行文件是完全正确的

另外,硬链接意味着可能有多个正确答案——如果
a.out
b.out
是硬链接的,那么没有一种简单的方法来判断
a.out
b.out
是用来启动程序运行的


您最好的选择可能是阅读
/proc/self/exe
,或者解析
/proc/self/cmdline
和/或
/proc/self/maps
BSD实用程序库有一个函数getprogname(3),它完全满足您的需要。我建议在这种情况下,它比procfs更便于携带和使用。

我不知道如何获取实际可执行文件的路径,但我认为使用
char[]
作为
dlinfo
的参数会使它复杂一些。为什么不使用
argv[0]
?这将在库中调用,而不是从可执行文件本身调用。我没有访问argv[0]的权限。您可能会争辩说,如果可执行文件希望获得路径,则应使用argv[0],但我无法控制这一点。我试图在linux上复制GetModuleFileName()的一些功能。我的代码目前使用/proc/self/exe,但我看到很多地方说它不可靠。我想我会坚持到现在,看看是否有任何问题。谢谢。
/proc/self/exe
确实是最好的选择,但请注意,这是特定于Linux的-它在macOS上不起作用,在Mingw上也不起作用(我相信)。这肯定会使代码不可移植。我只需要它在Linux上工作,所以这对我来说不是问题。谢谢。一个缺点:取消链接与删除不同。您当然可以在可执行文件运行时取消链接,mmap页面将保留在磁盘上,直到它们被取消映射。但是,除非将可执行文件加载到主内存中(通过交换或简单地流式加载到内存中),否则无法从磁盘中删除这些页面,而不会导致问题(Linux AFAIK无论如何都不允许这样做)。你是对的,如果你不习惯文件系统的工作方式,那么你可能会感到困惑。