守护进程 - 使用Unix套接字的客户端IPC

时间:2012-12-13 10:38:40

标签: objective-c macos ipc daemon

我有一个启动守护程序,我想要求用户应用程序提供状态信息。我使用unix套接字实现了一个客户端 - 服务器模型(将守护进程作为服务器),如下所述:OS X - Communication between launch daemon and launch agent

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

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

我对以下几点感到困惑:

  • 我必须在启动守护程序plist文件中指定套接字吗?怎么样?

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

  • 什么路径对unix socket有好处?技术说明建议/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");   
    //...
}

1 个答案:

答案 0 :(得分:1)

  • 你不应该在plist中指定套接字,你知道具体的地方,服务器知道,客户端知道,应该是应该的
  • plist中指定的套接字用于启动deamon / agent ondemand,在基本情况下不需要它
  • 你可以使用任何路径,如果你的守护进程首先启动(通常是这种情况)它有权在套接字上设置正确的权限,让任何人(或给定的用户,组)读,读,写或任何你希望获得权利,我确定你只是忘了让客户端写/读unix socket
  • 我认为在OSX上,unix socket IPC是一个完美,简单的解决方案(当然你还有许多其他选择,xpc,mach消息等)。
  • 你可以在它的plist(StandardOutPath,StandardErrorPath keys)中定义守护进程的stdout和stderr的位置