ユーザーアプリからステータス情報を要求したい起動デーモンがあります。ここで説明するように、UNIXソケットを使用してクライアントサーバーモデル(サーバーとしてデーモンを使用)を実装しました:OSX-起動デーモンと起動エージェント間の通信
実際、デーモンをユーザープロセス(デバッグ用)として実行するとうまく機能しますが、実際にrootとして起動すると失敗します。
デーモンとエージェントのTN およびデーモンとサービスのプログラミングガイドを読みました。ただし、起動デーモンでソケットをどのように使用する必要があるかについての適切な情報を見つけることができませんでした。
私はいくつかのことに混乱しています:
起動デーモンの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");
//...
}