我有一个启动守护程序,我想从用户应用程序中获取状态信息。我使用 unix 套接字实现了客户端-服务器模型(将守护进程作为服务器),如下所述:OS X - 启动守护进程和启动代理之间的通信
事实上,当我将守护进程作为用户进程(用于调试)运行时,它运行良好,但是当它实际以 root 身份启动时它会失败。
我已阅读TN on Daemons and Agents 和Daemon & 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");
//...
}