2009-10-13 18 views
7

Ich bin mir bewusst, dass jeder Prozess seine eigene Speicheradressraum schafft, aber ich habe mich gefragt,Ist es möglich, Funktionszeiger über Prozesse hinweg zu verwenden?

Wenn Verfahren A eine Funktion wie haben war:

int DoStuff() { return 1; } 

und einen Zeiger typedef wie:

typedef int(DoStuff_f*)(); 

und ein Getter-Funktion wie:

DoStuff_f * getDoStuff() { return DoStuff; } 

und eine magische Art und Weise mit Verfahren B zu kommunizieren über ... sagen boost :: inter

wäre es möglich, die Funktionszeiger übergeben B zu verarbeiten und

Verfahren A den DoStuff von Verfahren B direkt anrufen?

+2

Bitte geben Sie das O/S an, mit dem Sie es zu tun haben. Die Antwort auf die Frage ist für vxWorks im Vergleich zu Linux sehr unterschiedlich. – kmarsh

+2

Einverstanden - alle "Nein" Antworten sollten als "nicht portabel" und/oder "nicht auf meinem Betriebssystem" verstanden werden. Auf einigen Plattformen mit sehr leichten Betriebssystemen gibt es keinen geschützten Speicher, und es wird einfach funktionieren. –

+0

Ich nehme an, es ist Windows. Meine Annahme basiert auf frühen Macieks Fragen und dem Stil der Funktionsbenennung :) –

Antwort

8

Nein. Alles ein Funktionszeiger ist eine Adresse im Adressraum Ihres Prozesses. Es hat keinen intrinsischen Marker, der für verschiedene Prozesse einzigartig ist. Also, auch wenn Sie Ihre Funktionszeiger gerade passiert sind immer noch gültig sein, wenn Sie es über zu B verschoben haben, würde es diese Funktion im Namen des Prozess B. nennt

Zum Beispiel, wenn Sie

////PROCESS A//// 
int processA_myfun() { return 3; } 
// get a pointer to pA_mf and pass it to process B 

////PROCESS B//// 
int processB_myfun() { return 4; } // This happens to be at the same virtual address as pA_myfun 
// get address from process A 
int x = call_myfun(); // call via the pointer 
x == 4; // x is 4, because we called process B's version! 
hatten

Wenn Prozess A und B denselben Code ausführen, erhalten Sie möglicherweise identische Funktionen an identischen Adressen - aber Sie arbeiten weiterhin mit den Datenstrukturen und dem globalen Speicher von B! Die kurze Antwort lautet also: Nein, so wollen Sie das nicht!

Auch Sicherheitsmaßnahmen wie address space layout randomization könnten verhindern, dass diese Art von "Tricks" überhaupt funktioniert.

Sie verwirren IPC und RPC. IPC dient zum Übertragen von Daten, z. B. von Objekten oder einem Textblock. RPC bewirkt, dass Code in einem Remote-Prozess ausgeführt wird.

+0

+1 für ASLR - Ich habe versucht, Details darüber zu erinnern. –

0

Wenn beide Prozesse in der gleichen Anwendung sind, sollte dies funktionieren. Wenn Sie versuchen, Funktionszeiger zwischen Anwendungen zu senden, haben Sie Pech.

Meine ursprüngliche Antwort war korrekt, wenn Sie davon ausgehen, dass ein Prozess und ein Thread das gleiche sind, was sie nicht sind. Die anderen Antworten sind korrekt - verschiedene Prozesse können Funktionszeiger (oder jede andere Art von Zeigern, für diese Angelegenheit) nicht teilen.

+0

also mit anderen Worten: auch wenn ich boost :: interpcocess verwende, verwaltete Shared Memory-Segment (zum Beispiel) dann auch wenn ich den Zeiger übergeben - Es wird immer noch nicht funktionieren, richtig? – Maciek

+1

Ich weiß nichts über Boost, aber es ist egal, wie Sie die Zeiger zwischen den Prozessen kommunizieren. Wenn Ihr Programm mehrere Threads erzeugt, können Sie Zeiger zwischen ihnen übergeben. Wenn Sie zwei separate Anwendungen starten, können Sie dies nicht tun. –

+0

Bitte teilen Sie uns Ihre Definition von "Prozess" im Vergleich zu "Anwendung". – kmarsh

8

Kurz gesagt, Sie können den Funktionszeiger nicht verwenden, der an einen anderen Prozess übergeben wurde.

Funktionscodes befinden sich in geschützten Seiten des Speichers, Sie können nicht zu ihnen schreiben. Und jeder Prozess hat einen isolierten virtuellen Adressraum, so dass die Adresse der Funktion in einem anderen Prozess nicht gültig ist. In Windows können Sie die in Artikel this beschriebene Technik verwenden, um Ihren Code in einen anderen Prozess zu injizieren, aber die neueste Version von Windows lehnt dies ab.

Anstatt den Funktionszeiger zu übergeben, sollten Sie eine Bibliothek erstellen, die in beiden Prozessen verwendet wird. In diesem Fall könnten Sie eine Nachricht an einen anderen Prozess senden, wenn Sie diese Funktion aufrufen müssen.

1

Wenn Sie versucht haben, den Funktionszeiger von Prozess A aus Prozess B zu verwenden, würden Sie Prozess A nicht aufrufen - Sie würden an derselben Adresse in Prozess B anrufen. Wenn sie dasselbe Programm haben, könnten Sie Glück haben und es wird derselbe Code sein, aber es wird keinen Zugriff auf irgendwelche der in Prozess A enthaltenen Daten haben.

1

Ein Funktionszeiger funktioniert dafür nicht, da er nur die Startadresse für den Code enthält; Wenn der betreffende Code in dem anderen Prozess nicht vorhanden ist oder (aufgrund einer Randomisierung des Adressraums) sich an einem anderen Ort befindet, ist der Funktionszeiger nutzlos; im zweiten Prozess wird es auf etwas oder nichts zeigen, aber fast sicher nicht dort, wo du es haben willst.

Sie könnten, wenn Sie verrückt waren^Wdaring, kopieren Sie die eigentliche Befehlssequenz auf den gemeinsamen Speicher und dann den zweiten Prozess direkt zu springen - aber selbst wenn Sie dies zum Funktionieren bringen könnten, würde die Funktion noch laufen Prozess B, nicht Prozess A.

Es klingt wie, was Sie wollen, ist eigentlich eine Art Message-Passing oder RPC-System.

+0

Yep Nachricht übergeben. Bereits implementiert eines mit boost :: interprocess, fragte sich "andere Wege" – Maciek

1

Deshalb haben Menschen Dinge wie COM, RPC und CORBA erfunden. Jeder von ihnen gibt diese allgemeine Art von Fähigkeiten. Wie Sie sich denken, macht jeder die Arbeit ein bisschen anders als die anderen.

Boost IPC unterstützt keine Remote-Prozeduraufrufe. Es wird ermöglicht, eine Variable in Shared Memory zu setzen, so dass es für zwei Prozesse zugänglich ist, aber wenn Sie einen Getter/Setter verwenden wollen, um auf diese Variable zuzugreifen, müssen Sie das selbst tun.

Das sind alles Wrapper, um eine "schmackhafte" Version von etwas zu produzieren, das Sie ohne sie aber tun können. In Windows können Sie z. B. eine Variable selbst im Shared Memory ablegen. Sie können das Gleiche unter Linux tun. Die Boost-Bibliothek ist eine ziemlich "dünne" Bibliothek um diese, mit der Sie den gleichen Code für Windows oder Linux schreiben können, aber nicht versuchen, eine Menge darauf zu bauen. CORBA (für ein Beispiel) ist eine viel dickere Schicht, die eine relativ vollständige verteilte Umgebung bereitstellt.

Verwandte Themen