跨进程通信

🎯 它们在iOS开发中的位置

软件工程知识体系
├── 操作系统原理(IPC概念)
├── 特定平台深入
│ ├── iOS安全模型(沙盒、权限)
│ ├── 苹果系统架构(Mach内核)
│ └── 苹果开发框架(XPC、App Groups)
└── 实际开发应用
├── App Extension开发
├── 系统服务集成
└── 安全通信实现


App Groups是苹果提供的官方机制,允许同一开发者签名的多个进程(主 App、Extension、其他 App)共享一个公共的沙盒子目录(即共享容器),这个目录不属于任何单个进程的私有沙盒,而是由系统分配的公共空间。

通过App Groups创建的共享容器目录,不属于单个 App 的沙盒, 若仅删除主 App,共享容器中的数据仍保留(若有其他 Extension/App 绑定该 App Group,数据会被保留);

开发者后台开启 App Group 服务并创建标识,Xcode 中为 App/Extension Target 关联该标识,最终通过签名验证实现绑定。

Extension(应用扩展) 是苹果提供的一套开发框架,允许开发者为系统或主 App 添加特定功能模块,这些模块以独立进程的形式运行,

问题一:iOS 有哪些跨进程通信方式?XPC 和 Mach 端口的区别?

考察点:

  1. 系统知识广度:是否了解 iOS 系统中 IPC 的完整生态。
  2. 深度理解:能否区分不同层级(用户层/内核层)的通信机制。
  3. 技术演进认知:是否理解苹果官方推荐的技术演进方向(从 Mach 到 XPC)。

回答方案:
“iOS 的跨进程通信方式主要分为以下几个层次:

  1. 高层 API(最常用):

    • URL Scheme:通过 openURL: 或 UIApplication.shared.open 启动其他 App 或传递简单数据。适用于 App 间跳转。
    • App Groups & 共享容器:通过 UserDefaults(suiteName:)、FileManager 访问共享的 UserDefaults 或文件。适用于 App 与 Extension 之间共享数据。
    • Keychain Sharing:在配置了相同 Keychain Group 的应用间安全地共享密钥、密码等敏感信息。
  2. 系统级 IPC 框架(苹果官方推荐):

    • XPC:这是苹果当前最主推的跨进程通信框架。它提供了一套异步、基于消息的 C API(及 Foundation 层的 NSXPCConnection 封装)。XPC 的核心优势在于它内置了沙盒权限管理、生命周期管理和崩溃隔离。通信双方建立连接,一方崩溃不会导致另一方崩溃。
  3. 底层机制:

    • Mach 端口:这是 macOS/iOS 内核层最基础的 IPC 原语。XPC 和很多其他高层机制最终都是基于 Mach 端口实现的。它非常强大和灵活,但直接使用它异常复杂,需要处理消息序列化、端口权限、内存管理等底层细节,且容易引入安全漏洞。

关于 XPC 与 Mach 端口的区别:

  • 抽象层级:XPC 是高层框架,Mach 端口是底层原语。XPC 在 Mach 端口之上构建,封装了其复杂性。
  • 易用性与安全性:XPC 提供了安全的 API、自动的消息序列化(支持 NSSecureCoding 对象)和清晰的生命周期管理。直接使用 Mach 端口则对开发者要求极高,容易出错。
  • 用途:开发者几乎永远不应该直接使用 Mach 端口。XPC 是苹果希望我们使用的“正确方式”,用于实现插件、守护进程、系统服务等需要稳定安全通信的场景。

加分项:

  • 提到 CFMessagePort 或 Distributed Notifications(CFNotificationCenter),但指出它们在 iOS 上的限制(如后台限制、被 XPC 替代的趋势)。
  • 简要说明 XPC 的连接模型:NSXPCListener(服务端)和 NSXPCConnection(客户端),以及通过协议定义接口。

问题二:App Extension(如 Widget)和主 App 如何通信?为什么优先用 XPC?

考察点:

  1. 实战经验:是否真正开发过 Extension,了解其通信约束。
  2. 技术选型能力:能否根据场景选择最合适的方案。
  3. 对系统机制的理解:是否理解 XPC 在稳定性和安全性上的优势。

回答方案:
“App Extension 和主 App 是独立的进程,它们的通信方式主要有以下几种,选择时需考虑场景:

  1. 共享容器(App Groups):这是最常用、最简单的数据共享方式。通过将数据(如 UserDefaults、小文件、数据库)写入共享的 App Group 目录来实现单向或双向的数据同步。适用于 Widget 展示主 App 的最新数据这种场景。

    • 注意:需要处理文件读写冲突,通常使用 NSFileCoordinator。
  2. Keychain Sharing:用于共享登录态、令牌等敏感信息。确保主 App 登录后,Widget 也能获取认证状态。

  3. URL Scheme:通过 openURL: 唤起主 App 并传递简单指令。这是 Extension 主动唤醒主 App 的主要方式。例如,点击 Widget 的某个区域跳转到主 App 的特定页面。

为什么复杂通信要优先考虑 XPC?
当共享容器(文件/数据库)和简单的 URL 唤起无法满足需求,需要进行复杂的双向、实时、结构化数据通信时(例如,一个“键盘扩展”需要频繁从主 App 的词库服务查询数据),应该优先考虑使用 XPC。原因如下:

  • 崩溃隔离:Extension 或主 App 一方崩溃,不会导致另一方崩溃。如果用简单的 CFMessagePort 或共享内存,风险很高。
  • 权限精细控制:XPC 连接可以定义精细的沙盒权限,限制对方进程能执行的操作,更安全。
  • 生命周期管理:XPC 框架自动管理连接的生命周期和进程的唤醒/挂起,更省心。
  • 异步与性能:XPC 天生异步,消息序列化高效,适合高频通信。
  • 苹果的意图:XPC 是苹果为进程间通信设计的现代化框架,代表了最佳实践。

加分项:

  • 指出在 Widget 场景下,由于 Widget 的启动和生命周期非常短暂且由系统严格控制,高频的 XPC 通信可能不适用,优先使用共享容器做数据同步。XPC 更适用于“今天扩展”、“文件提供器扩展”等需要强交互的场景。
  • 提到 NSXPCConnection 的 remoteObjectProxy 和 remoteObjectProxyWithErrorHandler: 用于调用远程方法。

问题三:URL Scheme 的优缺点?如何保证通信安全性?

考察点:

  1. 辩证思维:能否全面评估一个技术的利弊。
  2. 安全意识:这是核心考察点,是否具备防御恶意调用的知识。
  3. 解决方案能力:能否提出具体的安全加固方案。

回答方案:
“URL Scheme 是 iOS 中实现 App 间跳转和简单通信的经典机制。

优点:

  • 简单易用:配置简单,实现快速。
  • 通用性强:是 iOS 上最古老的 App 间通信方式,几乎被所有 App 支持。
  • 可被系统检索:可以被 Spotlight 和 Siri 建议收录。
  • 跨平台潜力:在 Web 中也可以通过 window.location 尝试唤起。

缺点:

  • 安全性差(最大缺点):
    • Scheme 劫持:如果设备上安装了多个注册相同 Scheme 的 App,系统行为不确定(通常后安装的优先,但用户可选择)。
    • 参数伪造:任何 App 或网页都可以构造 URL 来调用你的 App,并传递恶意参数。
    • 没有身份认证:调用方身份无法被验证。
  • 功能受限:只能传递少量数据(URL 长度限制),且是单向异步通信。无法进行复杂的双向对话。
  • 依赖主线程:application:openURL:options: 回调在主线程。
  • 用户体验可能中断:会跳出当前 App。

如何保证通信安全性?
URL Scheme 本质是不安全的,但我们可以通过以下措施大幅提升安全性:

  1. 使用 Universal Links (iOS 9+):这是苹果推荐的替代方案。它使用标准的 HTTPS 链接和关联的域名,通过苹果的服务器进行验证,从根本上解决了 Scheme 劫持和伪造问题。只有你的网站域名的链接才能唤起你的 App。
  2. 为 URL Scheme 增加复杂度:使用自定义、随机化、不易猜测的 Scheme,降低被恶意扫描发现的风险(例如用 myapp-internal-v1:// 而非 myapp://)。
  3. 参数签名与校验:
    • 关键步骤:在 URL 的查询参数中附带一个加密签名(如 HMAC-SHA256)。
    • 共享密钥:通信双方(如自己的多个 App)预先在代码内或通过安全渠道(如 Keychain Sharing)共享一个密钥。
    • 签名生成:调用方对所有参数按固定规则排序、拼接,然后用密钥生成签名,附在 URL 中。
    • 签名验证:接收方收到 URL 后,用同样规则和共享密钥重新计算签名,并与传入的签名比对。不一致则立即拒绝。
  4. 增加一次性 Token:在 URL 中附带一个只能使用一次的随机数,服务器端或接收方记录已使用的 Token,防止重放攻击。
  5. 动作确认:对于敏感操作(如支付、修改账户),不要在唤起后直接执行,必须在 App 内让用户再次确认。

加分项:

  • 强调 Universal Links 是首选的安全方案,URL Scheme 应仅作为降级方案或用于不支持 Universal Links 的场景(如从第三方 App 跳回)。
  • 提到 application:openURL:options: 中的 sourceApplication 参数并不可靠,不能用于身份验证。
  • 简要描述一个签名方案的具体实现例子。

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容