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

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

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

  1. bool
  2. resolveBinaryLocation(string &binaryDirname)
  3. {
  4. // Read the symbolic link '/proc/self/exe'.
  5. const char *linkName = "/proc/self/exe";
  6. const size_t bufSize = PATH_MAX + 1;
  7. char dirNameBuffer[bufSize];
  8. const int ret = int(readlink(linkName, dirNameBuffer, bufSize - 1));
  9. if (ret == -1) {
  10. // Permission denied (We must be inetd with this app run as other than root).
  11. return false;
  12. }
  13. dirNameBuffer[ret] = 0; // Terminate the string with a NULL character.
  14. binaryDirname = dirNameBuffer;
  15. // Erase the name of the executable:
  16. string::size_type last = binaryDirname.size() - 1;
  17. string::size_type idx = binaryDirname.rfind(DSI_PATH_CHAR, last);
  18. // Add one to keep the trailing directory separator.
  19. binaryDirname.erase(idx + 1);
  20. return true;
  21. }
daupos2t

daupos2t1#

以下是我的解决方案:

  1. bool
  2. resolveBinaryLocation(string &binaryDirname)
  3. {
  4. const size_t bufSize = PATH_MAX + 1;
  5. char dirNameBuffer[bufSize];
  6. #ifdef __APPLE__
  7. uint32_t size = bufSize;
  8. if (_NSGetExecutablePath(dirNameBuffer, &size) != 0) {
  9. // Buffer size is too small.
  10. return false;
  11. }
  12. #else // not __APPLE__
  13. // Read the symbolic link '/proc/self/exe'.
  14. const char *linkName = "/proc/self/exe";
  15. const int ret = int(readlink(linkName, dirNameBuffer, bufSize - 1));
  16. if (ret == -1) {
  17. // Permission denied (We must be inetd with this app run as other than root).
  18. return false;
  19. }
  20. dirNameBuffer[ret] = 0; // Terminate the string with a NULL character.
  21. #endif // else not __APPLE__
  22. binaryDirname = dirNameBuffer;
  23. // Erase the name of the executable:
  24. string::size_type last = binaryDirname.size() - 1;
  25. string::size_type idx = binaryDirname.rfind(DSI_PATH_CHAR, last);
  26. // Add one to keep the trailing directory separator.
  27. binaryDirname.erase(idx + 1);
  28. return true;
  29. }
展开查看全部
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是否与您自己的相同-如果它们不同,则中止并显示错误消息(意味着在启动时出现了新版本的可执行文件)。如果不能选择中止,您可以尝试执行新版本。

相关问题