macOS双击启动Bundle应用时getppid()返回1的原因疑问
macOS双击启动Bundle应用时getppid()返回1的原因疑问
嘿,我完全懂你现在的疑惑——明明双击Finder里的App Bundle启动应用,按道理父进程应该是Finder,但getppid()却返回1,这确实有点反直觉对吧?
先梳理下你的场景:你开发了一款macOS GUI应用,同时支持以后台服务(Agent/Daemon)模式运行,在main.swift里通过ObjC++调用getppid()来判断启动模式,结果双击启动时getppid()返回了1,但你并没有做fork或创建新线程这类会让父进程变成init的操作,这就很让人困惑了。
其实这是macOS的Launch Services机制在背后起作用:
- 当你双击Finder里的App Bundle时,Finder并不会直接fork出子进程来运行你的应用,而是向系统的
launchservicesd进程发起请求,由它来负责启动你的应用。 launchservicesd是init进程(PID为1)的子进程,它创建你的应用进程完成启动后,会主动脱离和这个进程的父子关系,此时你的应用进程就会被init进程接管,所以getppid()自然就返回1了。
你更新里用top查到Safari和Xcode的PPID都是1,就是最好的佐证——这些系统自带的GUI应用也是通过Launch Services启动的,最终父进程都会变成init。
另外要提醒的是,用getppid()来区分GUI应用和后台服务(Agent/Daemon)其实不太可靠,因为正常双击启动的GUI应用也会得到PPID=1。你可以换更准确的判断方式:
- 检查应用是否关联了图形会话(比如判断
NSApplication.shared.windows是否能正常创建,或者查询当前是否有可用的显示设备) - 查看启动时的环境变量,比如
$HOME路径(Agent用当前用户的HOME,Daemon用/var/root,GUI应用也是当前用户的HOME,但可以结合其他变量如$DISPLAY判断) - 检查是否由
launchd加载:Agent/Daemon是通过launchd启动的,可以读取launchd相关的环境变量或配置标识
备注:内容来源于stack exchange,提问作者NightFuryLxD
相关产品推荐
相关产品推荐

