获取 "real" 父进程以防进程使用 launchd 间接生成
Getting the "real" parent process in case process spawned indirectly using launchd
我正在维护一个 OSX 工具,该工具可以显示从直接父级到其最早祖先(通常是已启动)的选定进程的父级树。
但是,如果被检查的进程是使用双击捆绑包图标等事件从 launchd 间接生成的,或者 运行 使用命令 bash 的进程 [=11],则此进程链可能会中断=].在这些情况下,我希望相应地看到 bash
或 finder
。
也许 XPC 消息传递层是答案,因为我假设这些事件通过此机制传递给 launchd。然而,其他可用的 OSX 框架总是受欢迎的。
编辑:
我知道如果一个进程在 运行 时自行分离,我无法恢复它的 ppid,但我的目标是跟踪启动进程创建的调用者。
感谢
您看到的是正确的行为。
当用户从 Finder 或在终端中使用 open
命令打开应用程序包时,Launch Services 负责执行该应用程序。
当应用程序被引入 OS X / macOS 时,它会根据其捆绑包标识符在 Launch Services 中注册,如捆绑包的 Info.plist
文件中所声明的那样。
当用户在终端中双击或使用 open
时,Launch Services 接收包标识符并启动先前注册的应用程序。
请注意,如果应用程序包的标识符不唯一,则会出现问题。对于具有相同版本和应用程序标识符的两个应用程序包,Launch Services 将执行它注册的第一个应用程序,但它可能不是用户认为的应用程序 运行!
相比之下,如果您使用终端直接执行应用程序包中的二进制文件,而不使用 open
,其父级将是终端使用的 shell 应用程序。例如:-
/Applications/Calculator.app/Contents/MacOS/Calculator
此功能未记录。它可能会在任何 OS 更新时中断。
typedef pid_t (*pidResolver)(pid_t pid);
pidResolver resolver = dlsym(RTLD_NEXT, "responsibility_get_pid_responsible_for_pid");
pid_t trueParentPid = resolver(pid);
a) 这个方法是私有的
b) 它需要root权限
例如:如果您启动 Safari.app,也会创建一个名为 "Safari Networking" 的新进程。
如果您在 Activity 监视器中检查它,您只会看到 ppid 为 1。
以上代码片段将 return Safari 进程的 pid。正如在看时所见
"All Processes, Hierarchically" 其中 "Safari Networking" 分组在 "Safari" 下。
我正在维护一个 OSX 工具,该工具可以显示从直接父级到其最早祖先(通常是已启动)的选定进程的父级树。
但是,如果被检查的进程是使用双击捆绑包图标等事件从 launchd 间接生成的,或者 运行 使用命令 bash 的进程 [=11],则此进程链可能会中断=].在这些情况下,我希望相应地看到 bash
或 finder
。
也许 XPC 消息传递层是答案,因为我假设这些事件通过此机制传递给 launchd。然而,其他可用的 OSX 框架总是受欢迎的。
编辑:
我知道如果一个进程在 运行 时自行分离,我无法恢复它的 ppid,但我的目标是跟踪启动进程创建的调用者。
感谢
您看到的是正确的行为。
当用户从 Finder 或在终端中使用 open
命令打开应用程序包时,Launch Services 负责执行该应用程序。
当应用程序被引入 OS X / macOS 时,它会根据其捆绑包标识符在 Launch Services 中注册,如捆绑包的 Info.plist
文件中所声明的那样。
当用户在终端中双击或使用 open
时,Launch Services 接收包标识符并启动先前注册的应用程序。
请注意,如果应用程序包的标识符不唯一,则会出现问题。对于具有相同版本和应用程序标识符的两个应用程序包,Launch Services 将执行它注册的第一个应用程序,但它可能不是用户认为的应用程序 运行!
相比之下,如果您使用终端直接执行应用程序包中的二进制文件,而不使用 open
,其父级将是终端使用的 shell 应用程序。例如:-
/Applications/Calculator.app/Contents/MacOS/Calculator
此功能未记录。它可能会在任何 OS 更新时中断。
typedef pid_t (*pidResolver)(pid_t pid);
pidResolver resolver = dlsym(RTLD_NEXT, "responsibility_get_pid_responsible_for_pid");
pid_t trueParentPid = resolver(pid);
a) 这个方法是私有的
b) 它需要root权限
例如:如果您启动 Safari.app,也会创建一个名为 "Safari Networking" 的新进程。 如果您在 Activity 监视器中检查它,您只会看到 ppid 为 1。
以上代码片段将 return Safari 进程的 pid。正如在看时所见 "All Processes, Hierarchically" 其中 "Safari Networking" 分组在 "Safari" 下。