Ich mache einen Vergleich verschiedener IPC-Mechanismen, die auf Mac OS X verfügbar sind (Pipes, Sockets, System V IPC usw.), und ich würde gerne sehen, wie Mach-Ports mit den höheren Alternativen verglichen werden. Ich bin jedoch auf ein sehr grundlegendes Problem gestoßen: Sendeberechtigungen für Ports über Prozesse hinweg (speziell über einen übergeordneten Prozess und einen untergeordneten Prozess).
Im Gegensatz zu Dateideskriptoren werden Ports normalerweise nicht in gegabelte Prozesse übertragen . Dies bedeutet, dass ein anderer Weg, sie zu übertragen, hergestellt werden muss. Nur die einzige relevante Seite, die ich darüber finden konnte, war diese , und sie behaupten in einem Update, dass ihre Methode nicht mehr funktioniert und nie garantiert wurde, obwohl diese Methode war vorgeschlagen von einem Apple Ingenieur im Jahr 2009 . (Es beinhaltete das Ersetzen des Bootstrap-Ports, und das macht XPC jetzt kaputt.) Der Ersatz, den sie vorschlagen, verwendet veraltete Funktionen, daher ist das keine sehr ansprechende Lösung.
Eine Sache, die mir an der alten Lösung gefallen hat, ist, dass Ports zwischen den Prozessen, die sie nutzten, ziemlich privat blieben. Es war nicht notwendig, die Existenz des Ports zu übertragen, genau wie Pipes (vom pipe
-Aufruf) einmal gespreizt arbeiten. (Ich werde wahrscheinlich damit leben, wenn es eine andere Lösung gibt, aber es ist ein bisschen nervig.)
Wie übermittelst du also ein Senderecht an einen Mach-Port von einem Elternprozess an einen Kindprozess?
bootstrap_register
ist veraltet, bootstrap_check_in
jedoch nicht und kann zum Registrieren Ihres Ports verwendet werden, der später vom untergeordneten Prozess mithilfe von bootstrap_look_up
abgerufen werden kann. (Dies bietet leider immer noch nicht die Privatsphäre, nach der Sie suchen.)
Eine Sache, die Sie versuchen könnten (obwohl es ein eklatanter Hack ist), ist das Ausspionieren der Ausnahmeports als Vererbungsmechanismus. Legen Sie einen benutzerdefinierten Port als Ausnahmeport im übergeordneten Element fest, verzweigen Sie das untergeordnete Element, lassen Sie das untergeordnete Element den benutzerdefinierten Port von seinem Ausnahmeport abrufen, senden Sie seinen Aufgabenport an das übergeordnete Element, setzt das übergeordnete Element den Ausnahmeport zurück und dann laufen die beiden von dort mit einem Kommunikationskanal ab. Siehe task_set_exception_ports()
.
Die empfohlene Lösung ist, Mach IPC nicht direkt zu verwenden, sondern Ihren Kindprozess als XPC-Dienst zu implementieren. In diesem Fall können Sie die XPC-API verwenden, die Mach IPC hinter der Szene verwendet, aber Sie müssen nicht mit Details umgehen. Sie haben eine einfache API zum Senden von XPC-Nachrichten im übergeordneten und eine einfache API zum Empfangen von XPC-Nachrichten im Client, die auch Antworten einfach zurückgeben kann. Das System wird alle harten Teile für Sie behandeln.
Wenn Sie die XPC-API nicht verwenden können, beachten Sie, dass wenn Sie Ihren Dienst mit bootstrap_check_in()
registrieren (was nicht veraltet ist), er nicht privat ist, aber wenn Sie dies in einem Benutzerraumprozess tun wird für Ihre Login-Sitzung privat sein: root-Prozesse sehen sie nicht, Prozesse anderer Benutzer auch nicht. Wenn Sie dies in einem Root-Prozess tun, ist es jedoch für alle Sitzungen sichtbar.
Beachten Sie jedoch auch, dass Sie steuern können, wer Ihnen IPC-Nachrichten senden darf und wer nicht. Sie können mach_msg_audit_trailer_t
anfordern, wenn Sie eine Mach-Nachricht erhalten. Auf diese Weise erhalten Sie Zugriff auf die audit_token_t
des Absenders. Und mit audit_token_to_pid()
können Sie den pid_t
des Absenders erhalten. Da Sie die PID Ihres Kindes kennen, können Sie einfach alle Nachrichten ignorieren (indem Sie sie an mach_msg_destroy()
übergeben, um Ressourcenverluste zu vermeiden), es sei denn, die Nachricht wurde von Ihrem Kindprozess gesendet. Sie können also nicht verhindern, dass Ihr Port entschlüsselt wird, aber Sie können vermeiden, dass ein anderer Prozess als Ihr untergeordneter Prozess diesen Port verwendet.
Und zu guter Letzt können Sie Ihrem Port einfach einen zufälligen Namen geben, denn nur Ihr Kindprozess muss es wissen, damit Sie dynamisch einen Namen im Elternprozess generieren und ihn an Ihr Kind weitergeben können So kann Ihr Port angezeigt werden, wenn die Software nach Ports sucht, aber die meisten Programme verwenden sowieso nur fest codierte Namen.