我有一个启动守护程序,我想要求用户应用程序提供状态信息。我使用unix套接字实现了一个客户端 - 服务器模型(将守护进程作为服务器),如下所述:OS X - Communication between launch daemon and launch agent
事实上,当我将守护进程作为用户进程运行(用于调试)时它运行良好,但是当它以root身份实际启动时它将失败。
我已阅读TN on Daemons and Agents和Daemon & 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");
//...
}
答案 0 :(得分:1)