c++ Macintosh OS X Mavericks上的/proc/self/exe的等价物是什么?

6ojccjat  于 2023-06-25  发布在  Mac
关注(0)|答案(2)|浏览(203)

我正在将一个Linux C03应用程序移植到达尔文OS X上,并且有一些代码可以读取/proc/self/exe中的符号链接,以确定正在运行的可执行文件所在的目录。
如何计算当前运行在Macintosh达尔文OS X Mavericks上的C
可执行文件的目录?
下面是我在Linux上运行的代码:

bool
resolveBinaryLocation(string &binaryDirname)
{
  // Read the symbolic link '/proc/self/exe'.
  const char *linkName = "/proc/self/exe";
  const size_t bufSize = PATH_MAX + 1;
  char dirNameBuffer[bufSize];
  const int ret = int(readlink(linkName, dirNameBuffer, bufSize - 1));

  if (ret == -1) {
    // Permission denied (We must be inetd with this app run as other than root).
    return false;
  }

  dirNameBuffer[ret] = 0; // Terminate the string with a NULL character.

  binaryDirname = dirNameBuffer;

  // Erase the name of the executable:
  string::size_type last = binaryDirname.size() - 1;
  string::size_type idx  = binaryDirname.rfind(DSI_PATH_CHAR, last);

  // Add one to keep the trailing directory separator.
  binaryDirname.erase(idx + 1);

  return true;
}
daupos2t

daupos2t1#

以下是我的解决方案:

bool
resolveBinaryLocation(string &binaryDirname)
{
  const size_t bufSize = PATH_MAX + 1;
  char dirNameBuffer[bufSize];

#ifdef __APPLE__
  uint32_t size = bufSize;

  if (_NSGetExecutablePath(dirNameBuffer, &size) != 0) {
    // Buffer size is too small.
    return false;
  }
#else // not __APPLE__
  // Read the symbolic link '/proc/self/exe'.
  const char *linkName = "/proc/self/exe";
  const int ret = int(readlink(linkName, dirNameBuffer, bufSize - 1));

  if (ret == -1) {
    // Permission denied (We must be inetd with this app run as other than root).
    return false;
  }
    
  dirNameBuffer[ret] = 0; // Terminate the string with a NULL character.
#endif // else not __APPLE__

  binaryDirname = dirNameBuffer;

  // Erase the name of the executable:
  string::size_type last = binaryDirname.size() - 1;
  string::size_type idx  = binaryDirname.rfind(DSI_PATH_CHAR, last);

  // Add one to keep the trailing directory separator.
  binaryDirname.erase(idx + 1);

  return true;
}
v6ylcynt

v6ylcynt2#

值得一提的是,/proc/self/exe_NSGetExecutablePath不等价。如果可执行文件在运行时被删除或替换,则打开/proc/self/exe仍将打开可执行文件的运行版本,而打开_NSGetExecutablePath将失败(如果已删除)或改为打开新版本
如果重要的是要获得一个与/proc/self/exe等效的macOS,即使可执行文件被删除/替换,一个选项是在启动期间打开_NSGetExecutablePath的FD并保持打开状态。假设FD为3,那么/dev/fd/3的行为 * 大部分 * 类似于Linux /proc/self/exe,包括删除/替换可执行文件时的相同行为。(一个区别是你可以在Linux上使用/proc/self/exe进行自我执行,而macOS没有fexecveapparently不会让你在/dev/fd中执行任何东西。
从理论上讲,这里可能存在竞态条件:在启动和打开自身之间,可执行文件可以被新版本替换或删除。人们可能会认为这样的竞争条件非常罕见,因此没有必要担心它;但如果要处理的话,我有两个建议:

  • 如果在启动时,打开_NSGetExecutablePath()返回的路径失败(可执行文件在启动时被删除,或其他一些奇怪的情况)-只需中止并显示错误消息。
  • 检查您打开的可执行文件的LC_UUID是否与您自己的相同-如果它们不同,则中止并显示错误消息(意味着在启动时出现了新版本的可执行文件)。如果不能选择中止,您可以尝试执行新版本。

相关问题