使用 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
文件同步.
注意:由于这是基于NSUserDefaults
,value
对象必须是属性列表对象(NSString
、NSNumber
、NSArray
、NSDictionary
、NSDate
、NSData
、...)。参见 Preferences and Settings Programming Guide。
我的目标是开发可以在进程之间共享的健壮、连贯和持久的数据库,只需列出 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
文件同步.
注意:由于这是基于NSUserDefaults
,value
对象必须是属性列表对象(NSString
、NSNumber
、NSArray
、NSDictionary
、NSDate
、NSData
、...)。参见 Preferences and Settings Programming Guide。