0

我有一个启动守护程序,我想从用户应用程序中获取状态信息。我使用 unix 套接字实现了客户端-服务器模型(将守护进程作为服务器),如下所述:OS X - 启动守护进程和启动代理之间的通信

事实上,当我将守护进程作为用户进程(用于调试)运行时,它运行良好,但是当它实际以 root 身份启动时它会失败。

我已阅读TN on Daemons and AgentsDaemon & Services Programming Guide。但是,我找不到在启动守护程序中必须如何使用套接字的正确信息。

我对几件事感到困惑:

  • 我必须在启动守护进程 plist 文件中指定套接字吗?如何?

  • 如果在 plist 中指定了套接字,这是否会改变我需要在代码中创建套接字的方式?

  • 什么路径对 unix 套接字有好处?技术说明建议/var/run,但我猜用户进程可能不会写在那里,或者可以吗?

  • 是否有更简单的方法在守护进程和客户端之间进行 IPC?

  • 记录守护程序输出的最佳方法是什么。我尝试了 NSLog 但它似乎不起作用......


我也不确定我的套接字代码是否正确。也许更有经验的人可以告诉我我是否在正确的轨道上。我在守护进程中有以下代码来初始化 unix 套接字:

#define SOCKETNAME  "/var/run/com.company.myApp.socket"

- (void) startServer {
    //remove any prev socket
    unlink(SOCKETNAME);
    CFSocketContext CTX = { 0, (__bridge void *)(self), NULL, NULL, NULL };

    CFSocketRef unixSocket = CFSocketCreate(NULL, PF_UNIX, SOCK_STREAM, 0,
                               kCFSocketAcceptCallBack, (CFSocketCallBack)AcceptCallBack, &CTX);
    if (unixSocket == NULL) {/*log and return*/} 

    struct sockaddr_un addr;
    memset(&addr, 0, sizeof(addr));
    addr.sun_family = AF_UNIX;
    strcpy(addr.sun_path, SOCKETNAME);
    addr.sun_len = strlen(addr.sun_path) + sizeof (addr.sun_family);

    NSData *address = [ NSData dataWithBytes: &addr length: sizeof(addr) ];
    if (CFSocketSetAddress(unixSocket, (__bridge CFDataRef) address) != kCFSocketSuccess) {
        NSLog(@"CFSocketSetAddress() failed\n");
        CFRelease(unixSocket);
    }

    CFRunLoopSourceRef sourceRef = CFSocketCreateRunLoopSource(kCFAllocatorDefault, unixSocket, 0);
    CFRunLoopAddSource(CFRunLoopGetCurrent(), sourceRef, kCFRunLoopCommonModes);
    CFRelease(sourceRef);    
    CFRunLoopRun();
}


void AcceptCallBack(CFSocketRef socket, CFSocketCallBackType type, CFDataRef address, const void *data, void *info) {
    CTServerController* selfServerController = (__bridge CTServerController*) info;
    //NSLog(@"acceptCallBack");   
    //...
}
4

1 回答 1

1
  • 你不应该在plist中指定套接字,你知道具体的地方,服务器知道,客户端知道,应该足够了
  • plist 中指定的套接字用于按需启动守护程序/代理,在基本情况下您不需要它
  • 您可以使用任何路径,如果您的守护程序首先启动(通常是这种情况),它有权在套接字上设置正确的权限,以让任何人(或给定的用户、组)读取、读取和写入或您的任何给定权限希望,我确定您只是忘记让客户端写入/读取 unix 套接字
  • 我认为在 OSX 上,unix 套接字 IPC 是一个完美、简单的解决方案(当然,您还有许多其他选择,xpc、mach 消息等)
  • 您可以在它的 plist 中定义守护程序的 stdout 和 stderr 的位置(StandardOutPath,StandardErrorPath 键)
于 2013-07-17T10:17:12.113 回答