0

ユーザーアプリからステータス情報を要求したい起動デーモンがあります。ここで説明するように、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");   
    //...
}
4

1 に答える 1

1
  • plistでソケットを指定するべきではありません、あなたは具体的な場所を知っています、サーバーは知っています、クライアントは知っています、それは十分なはずです
  • plistで指定されたソケットは、デーモン/エージェントをオンデマンドで起動するためのものです。基本的なケースでは必要ありません。
  • 任意のパスを使用できます。デーモンが最初に起動する場合(通常は)、デーモンはソケットに正しい権限を設定するすべての権限を持ち、誰でも(または特定のユーザー、グループ)に読み取り、読み取り、書き込み、または任意の権限を与えることができます。クライアントにUNIXソケットの書き込み/読み取りを許可するのを忘れたと思います
  • OSXでは、UNIXソケットIPCは完璧で簡単なソリューションだと思います(もちろん、xpc、machメッセージなど、他にも多くの選択肢があります)
  • plistでデーモンのstdoutとstderrをどこに移動するかを定義できます(StandardOutPath、StandardErrorPathキー)
于 2013-07-17T10:17:12.113 に答える