2012-02-10 72 views
1

我正在MAC OS上开发应用程序。它有2个部分 - 一个UI元素和一个守护进程(它需要连续运行,并且必须在被终止时重新启动)。目前我正在使用launchctl来重新启动守护程序。Mac OS中的通信问题

但还有另一个问题。我需要我的应用程序的两部分相互沟通。为此我使用相同的分布对象(如给出here)。但是,当我使用launchctl启动守护进程时,这不起作用。任何人都可以提出一些替代?

回答

2

我使用NSDistributedNotifications在一个应用程序中处理这个问题,甚至在10.7上。您必须自己动手握手,因为这可能是有损的(即包含ack通知并在超时情况下重新发送)。这种方法的一个副作用是,如果有多个客户端正在运行(特别是在快速用户切换下),他们都会收到通知。这在这个应用程序的特殊情况下很好。实施起来也非常简单。

对于另一个应用程序,我使用了两个FIFO。服务器写入一个并从另一个读取。客户做的是相反的。您当然也可以使用网络套接字来实现相同的功能。我倾向于选择FIFO,因为您不必处理锁定网络套接字。

这就是说,你看到使用launchd下的分布式对象有什么问题?你刚才看到10.7的问题(它改变了启动环境的规则)?

您是否在使用launchd在端口被访问时延迟加载守护程序(这是执行此操作的常用方法)。你有没有考虑使用launchchagent而不是launchdaemon?


编辑:

啊......引导服务器。是。你需要在正确的引导环境中执行,以便与他们交谈。登录会话的引导环境根源于windowserver进程。 LaunchDaemons运行在不同的上下文中,因此它们无法直接与登录会话进行通信。一些背景阅读:

我不知道反正拿到进程进入正确的上下文,而无需使用launchctl bsexec。技术上推出了一个API(launchctl使用它),但它没有很好的文档。您可以从opensource.apple.com取得source

即使你留在NSDistributedObject,我会尝试使用除引导服务以外的东西,如果可以的话。正如我所提到的,我倾向于使用其他工具并避免NSDistributedObject。在我看来,出于同样的原因,REST比SOAP更好,简单的协议通常比远程对象更好。 (YMMV)

+0

对于分布式对象,我在[NSMachBootstrapServer sharedInstance]上注册了我的连接。但是这个函数为我的应用程序和守护进程返回的对象是不同的。直到我只使用sudo启动守护进程时,它工作正常,但它停止使用sudo launchctl。你能提出建议吗? – 2012-02-17 11:48:09

1

如果您使用sudo launchctl启动守护进程, IPC不应使用CFMessagePortDistributed objectCFMessagePortDistributed object是使用引导程序服务实现的(许多Mac OS X子系统通过与中央服务交换Mach消息来工作。要使这样的子系统正常工作,它必须能够找到服务。这通常使用Mach引导程序服务完成,它允许进程按名称查找服务)。 如果您将使用DO or CFMessagePort;你会遇到bootstrap命名空间问题。 当你将启动你的守护进程使用sudo launchctl;您的服务在根引导程序名称空间中注册,因此您的客户端(以用户模式运行)将无法使用该服务。
您可以使用

$ launchctl bslist 
$ sudo launchctl bslist // If you are using sudo lunchctl 

检查引导服务,您应该使用UNIX Domain Sockets。 UNIX域套接字有点像TCP/IP套接字,除了通信总是本地到计算机。您可以使用您将用于TCP/IP套接字的相同BSD套接字API访问UNIX域套接字。主要区别是地址格式。对于TCP/IP套接字,地址结构(通过绑定,连接等传递的地址)是(struct sockaddr_in),其中包含IP地址和端口号。对于UNIX域套接字,地址结构为(struct sockaddr_un),其中包含一个路径。有关在客户端/服务器环境中使用UNIX域套接字的示例,请参阅示例代码'CFLocalServer'
在此Technical Note TN2083 Daemons and Agents
Daemon IPC Recommendations
Mach Bootstrap Basics

每个用户都有一个单独的命名空间马赫。你不能命名空间之间沟通 看看。您需要使用套接字(NSSocketPort) ,而不是以这种方式进行限制。 [1]