2 Stimmen

Ersetzen von getpid durch meine eigene Implementierung

Ich habe eine Anwendung, in der ich eine neue getpid-Funktion schreiben muss, um die Originalfunktion des Betriebssystems zu ersetzen. Die Implementierung wäre ähnlich wie:

pid_t getpid(void)
{
    if (gi_PID != -1)
    {
        return gi_PID;
    }
    else
    {
        // Betriebssystem-Level getpid() Funktion
    }
}

Wie kann ich die ursprüngliche getpid() Implementierung des Betriebssystems durch diese Funktion aufrufen?

EDIT: Ich habe Folgendes versucht:

pid_t getpid(void)
{
    if (gi_PID != -1)
    {
        return gi_PID;
    }
    else
    {
        return _getpid();
    }
}

wie Jonathan vorgeschlagen hat. Dies hat mir die folgenden Fehler bei der Kompilierung mit g++ gegeben:

Bei der Funktion pid_t getpid()': SerendibPlugin.cpp:882: Fehler: _getpid' nicht deklariert (erste Verwendung dieser Funktion) SerendibPlugin.cpp:882: Fehler: (Jedes nicht deklarierte Symbol wird nur einmal für jede Funktion gemeldet, in der es erscheint.)

EDIT 2: Ich habe es geschafft, dies zu erreichen, indem ich einen Funktionszeiger verwendet und ihn auf das nächste Folgesymbol mit der ID "getpid" gesetzt habe, indem ich dlsym(RTLD_NEXT, "getpid") verwendet habe.

Hier ist mein Beispielcode:

vi xx.c
"xx.c" 23 Zeilen, 425 Zeichen 
#include 
#include 
#include 
#include 
#include 

using namespace std;
pid_t(*___getpid)();

pid_t getpid(void)
{
    cout << "Mein getpid" << endl;
    cout << "PID :" << (*___getpid)() << endl;
    return (*___getpid)();
}

int main(void)
{
    ___getpid = (pid_t(*)())dlsym(RTLD_NEXT, "getpid");
    pid_t p1 = getpid();
    printf("%d \n", (int)p1);
    return(0);
}

g++ xx.c -o xout

Mein getpid
PID :7802
7802

4voto

Jonathan Leffler Punkte 694013

Auf vielen Systemen finden Sie, dass getpid() ein 'schwaches Symbol' für _getpid() ist, das anstelle von getpid() aufgerufen werden kann.


In der ersten Version der Antwort wurde __getpid() erwähnt; die Erwähnung wurde schnell entfernt, da sie fehlerhaft war.

Dieser Code funktioniert für mich unter Solaris 10 (SPARC) - mit einem C++-Compiler:

#include 
#include 
#include 

extern "C" pid_t _getpid();

pid_t getpid(void)
{
    return(-1);
}

int main(void)
{
    pid_t p1 = getpid();
    pid_t p2 = _getpid();
    printf("%d vs %d\n", (int)p1, (int)p2);
    return(0);
}

Dieser Code funktioniert für mich unter Solaris 10 (SPARC) - mit einem C-Compiler:

Black JL: cat xx.c
#include 
#include 
#include 

pid_t getpid(void)
{
    return(-1);
}

int main(void)
{
    pid_t p1 = getpid();
    pid_t p2 = _getpid();
    printf("%d vs %d\n", (int)p1, (int)p2);
    return(0);
}
Black JL: make xx && ./xx
cc     xx.c   -o xx
"xx.c", line 13: warning: implicit function declaration: _getpid
-1 vs 29808
Black JL:

1voto

Jérôme Punkte 2540

Sie können ein Makro verwenden:

in einer .h-Datei, die in jeder Datei eingefügt wird, in der Sie die getpid-Funktion ersetzen möchten

#define getpid() mygetpid()

Dann legen Sie Ihre eigene Implementierung in einer .cpp-Datei ab

pid_t mygetpid() {
    // tun Sie, was Sie möchten
    return (getpid)();
}

0voto

JaredPar Punkte 699699

Sie verwenden die Terminologie ein wenig falsch. Es ist nicht möglich, getpid() zu überschreiben, weil es keine virtuelle Funktion ist. Alles, was Sie tun können, ist zu versuchen, getpid durch verschiedene böse Mittel mit einer anderen Funktion zu ersetzen.

Aber ich muss fragen, warum machen Sie das? Wenn Sie getpid ersetzen, bedeutet das, dass jedes Komponente, das vom Rückgabewert von getpid abhängig war, nun Ihr vermutlich modifiziertes Ergebnis erhält. Diese Änderung birgt ein sehr hohes Risiko, dass eine andere Komponente verändert wird.

Was Sie anbieten, ist eine neue Funktionalität und sollte daher eine andere Funktion sein.

Abgesehen davon, wenn Sie diesen Ansatz wirklich verfolgen wollen, ist der beste Weg das dynamische Laden der Funktion. Die originale DLL wird immer noch die getpid-Funktion enthalten und Sie können darauf über eine Kombination von LoadLibrary/GetProcAddress unter Windows oder dlopen/dlsym unter Linux zugreifen. Wenn Sie ein anderes Betriebssystem verwenden, geben Sie dies bitte an.

BEARBEITEN Antwort auf Kommentare, dass getpid testbar sein muss

Wenn Testbarkeit das Anliegen ist, warum haben Sie nicht stattdessen eine benutzerdefinierte getpid-Methode für Ihre Anwendung. Zum Beispiel, applicationGetPid(). Während normaler Ausführung könnte dies einfach an die System-getpid-Funktion weitergeleitet werden. Während unit tests könnte es verwendet werden, um vorhersehbarere Werte zu liefern.

pid_t applicationGetPid() { 
#if UNIT_TEST
return SomeCodeForUnitTests;
#else
return getpid();
#endif
}

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X