使用 XPC 在 macOS 中实现多进程共享数据库

implementing multi-process shared DB in macOS using XPC

我的目标是开发可以在进程之间共享的健壮、连贯和持久的数据库,只需列出 Windows 注册表。

在上一个问题中,我建议不要使用 CFPreferences(和 NSUserDefaults),原因如下

Current versions of macOS have a great deal of difficulty, and sometimes outright refuse, to update the values in one process with the values set by a second process.

或者,我建议使用以下方法:

To have one process responsible for all of the shared values and the other processes get/set those values via XPC.

XPC 对我来说很新,但从我目前所读的内容来看,它似乎为每个连接使用 GCD 队列,所以如果有多个进程要求访问同一个数据库,我如何保持一致性R/W 操作(我如何强制单线程执行所有队列中的项目)。

此外,我想让这个数据库满足 ACID 要求,我该如何实现?

这是我的建议,以及我在应用程序中使用的解决方案。

(1) 创建命名 XPC 服务。

如果您需要从多个应用程序连接您的服务,您需要使用 launchd 命名并注册您的服务应用程序。

(XPC 使创建仅供您的应用程序使用的匿名服务变得非常容易,但从其他应用程序连接会变得有点棘手。从 Daemons and Services Programming Guide 开始。)

请注意,在我的解决方案中,我已经在 launchd 中注册了一个用户代理,因此这只是继续执行步骤 (2) 的问题。

(2) 添加 XPC 消息处理程序以获取和设置您要共享的值。

- (void)queryPreferenceForKey:(NSString*)key withReply:(void(^)(id value))reply
{
    reply([[NSUserDefaults standardUserDefaults] objectForKey:key]);
}

- (void)setPreferenceValue:(id)value forKey:(NSString*)key withReply:(void(^)(BOOL changed))reply
{
    BOOL changed = NO;
    id previous = [[DDUserPreferences standardUserDefaults] objectForKey:key];
    if (!OBJECTS_EQUAL(previous,value))
        {
        [[NSUserDefaults standardUserDefaults] setObject:value forKey:key];
        changed = YES;
        }
    reply(changed);
}

(3)没有第3步

基本上就是这样。 NSUserDefault class 是线程安全的,因此没有并发问题,它会自动负责序列化 属性 值并将它们与应用程序的持久默认值 .plist 文件同步.

注意:由于这是基于NSUserDefaultsvalue对象必须是属性列表对象(NSStringNSNumberNSArrayNSDictionaryNSDateNSData、...)。参见 Preferences and Settings Programming Guide