1

我想在没有使用 C++ 代码的 root 权限的情况下获取正在运行的进程(可执行文件)的完整路径。有人可以建议一种方法来实现这一点。

在 Linux 平台上,我可以使用以下方式来做到这一点。

char exepath[1024] = {0};
char procid[1024] = {0};
char exelink[1024] = {0};

sprintf(procid, "%u", getpid());

strcpy(exelink, "/proc/");
strcat(exelink, procid);
strcat(exelink, "/exe");

readlink(exelink, exepath, sizeof(exepath));

这里 exepath 为我们提供了可执行文件的完整路径。

同样,对于 Windows,我们使用

GetModuleFileName(NULL, exepath, sizeof(exepath));  /* get fullpath of the service */

请帮助我如何在 HP-UX 上执行此操作,因为 HP-UX 中没有 /proc 目录。

4

5 回答 5

9

首先,我想评论一下您的 Linux 解决方案:它大约是需要的 5 倍,并且执行了许多完全不必要的操作,以及使用 1024 幻数,这是完全错误的:

$ grep PATH_MAX /usr/include/linux/limits.h 
#define PATH_MAX        4096    /* # chars in a path name */

这是一个正确的最小替换:

#include <limits.h>
...
  char exepath[PATH_MAX] = {0};
  readlink("/proc/self/exe", exepath, sizeof(exepath));

其次,在 HP-UX 上,您可以使用它shl_get_r()来获取有关所有已加载模块的信息。在索引 0 处,您将找到有关主可执行文件的信息。将desc.filename指向当时可执行文件的名称execve(2)

不幸的是,该名称是相对的,因此您可能必须搜索$PATH,并且如果应用程序搜索putenv("PATH=some:new:path")或如果原始 exename 是 eg./a.out并且应用程序从那时起执行,则可能会失败chdir(2)

于 2008-11-09T07:24:41.120 回答
4

在 HP-UX 上,使用 pstat:

#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#include <unistd.h>

#define _PSTAT64
#include <sys/pstat.h>

int main(int argc, char *argv[])
{
  字符文件名[PATH_MAX];
  结构 pst_status s;

  if (pstat_getproc(&s,sizeof(s),0,getpid()) == -1) {
    perror("pstat_getproc");
    返回 EXIT_FAILURE;
  }

  if (pstat_getpathname(filename,sizeof(filename),&s.pst_fid_text) == -1) {
    perror("pstat_getpathname");
    返回 EXIT_FAILURE;
  }

  printf("文件名: %s\n",文件名);

  返回 EXIT_SUCCESS;
}
于 2009-01-23T14:52:24.167 回答
1

出于什么目的需要可执行路径?请记住,正如我在之前的帖子中所说,不能保证可执行文件的路径会存在,或者它是唯一的。

于 2008-10-17T19:25:07.957 回答
1

较早的关于 Unix Programming FAQ 的答案是正确的。问题是,即使使用 Linux /proc 的答案,可执行文件的路径自 exec() 以来可能已更改。事实上,可执行文件可能已被删除。考虑链接(包括符号链接和硬链接)会产生进一步的复杂性——同一个可执行文件可能有多个路径。没有涵盖所有情况的通用答案,因为可能没有剩余路径,如果有路径,它可能不是唯一的。

也就是说,使用 argv[0] 和一些逻辑,正如 cjhuit 之前所提倡的,可能会在 99.9% 的时间里做你想做的事。在进行相对路径检查之前,我会添加对包含“/”的路径的检查(请注意,您必须在任何 cwd() 调用之前执行此操作)。请注意,如果您的调用程序感觉很调皮,那么在 fork() 和 exec() 之间可以做很多事情来搞砸它。不要依赖它来处理可能影响应用程序安全性的任何事情(例如配置文件的位置)。

于 2008-10-14T16:20:45.147 回答
0

我以前在一般情况下这样做过。大致思路是抓取argv[0],对其进行一些处理:

int main( int argc, char** argv )
{
  string full_prog_path = argv[0];
  if ( full_prog_path[0] == "/" )
  {   // It was specified absolutely; no processing necessary.
  }
  else
  {
    string check_cwd = getcwd();
    check_cwd += argv[0];
    if ( FileExists( check_cwd ) )
    { // It was specified relatively.
      full_prog_path = check_cwd;
    }
    else
    { // Check through the path to find it
      string path = getenv( "PATH" );
      list<string> paths = path.split( ":" );
      foreach( test_path, paths )
      {
        if ( FileExists( test_path + argv[0] ) )
        { // We found the first path entry with the program
          full_prog_path = test_path + argv[0];
          break;
        }
      }
    }
  }

  cout << "Program path: " << full_prog_path << endl;

  return 0;
}

显然,这有一些假设可能会在某些时候打破,但它应该适用于大多数情况。

于 2008-10-14T13:54:23.663 回答