【问题标题】:Cross-user and cross-process shared settings跨用户跨进程共享设置
【发布时间】:2010-11-23 04:36:29
【问题描述】:
我有两个进程 - 一个用户进程和一个根级 LaunchDaemon。我希望两个进程都有共享设置。我尝试通过 sqlite 数据库使其工作,但遇到了损坏问题。我考虑过使用NSUserDefaults,但NSGlobalDomain 似乎只对用户是全局的,我需要一个跨用户的持久域,NSUserDefaults 似乎没有提供。
我已经尝试直接读取和写入 XML 文件,我可以让它在多个线程中正常工作(通过简单的 NSLock),但是当我尝试将 O_EXLOCK 应用于文件以防止一个从写入文件的过程,而另一个是,它似乎不起作用。
CFPreferences 似乎与NSUserDefaults 有大部分相同的问题。有一个kCFPreferencesAnyUser 常量,但文档说我只能在我有管理员权限(用户进程没有)的情况下使用它。
所以我的问题是:
如何有效实现跨进程、跨用户共享设置?
【问题讨论】:
标签:
objective-c
cocoa
settings
【解决方案1】:
您最好的选择可能是 O_EXLOCK 方法,为了方便起见,将其封装在 NSFileHandle 中 (-initWithFileDescriptor:)。像这样的东西(未经测试;未编译):
写作:
int fd = open([path UTF8String], O_TRUNC|O_EXLOCK);
if (fd >= 0)
{
NSFileHandle *fh = [[NSFileHandle alloc] initWithFileDescriptor:fd closeOnDealloc:YES];
[fh writeData:xmlData]; // Creating xmlData left as exercise for the reader
[fh release];
}
else // Error stuff
阅读:
int fd = open([path UTF8String], O_RDONLY|O_SHLOCK);
if (fd >= 0)
{
NSFileHandle *fh = [[NSFileHandle alloc] initWithFileDescriptor:fd closeOnDealloc:YES];
NSData *xmlData = [fh readDataToEndOfFile];
[fh release];
}
else // Error stuff
当然这些会阻塞,所以您需要使用 O_NONBLOCK 或将它们放在非 UI 线程上,这样您的 GUI 应用程序就不会乱跑。
O_EXLOCK 遇到什么问题?
【解决方案2】:
请注意,将O_EXLOCK 和O_SHLOCK 与open(2) 一起使用只会让您避免调用flock(2)。 Mac OS X 仅支持咨询锁定,并且,正如 flock() 的手册页所述:
咨询锁允许协作进程对文件执行一致的操作,但不保证一致性(即,进程仍然可以在不使用咨询锁的情况下访问文件,这可能会导致不一致)。
如果两个应用程序在每次打开咨询锁定文件时都没有选择加入咨询锁定系统,那么您会遇到问题。
您也可以尝试让用户进程使用 RPC 通过守护进程进行默认调用。然后它将代表客户端应用程序处理所有默认写入;默认读数已经命中任何用户、当前主机/任何主机默认值。