2009-04-28 3 views
2

У меня есть приложение, где мне нужно написать новую функцию getpid для замены оригинальной ОС. Реализация будет выглядеть следующим образом:Замена getpid моей собственной реализацией

pid_t getpid(void) 
{ 
    if (gi_PID != -1) 
    { 
     return gi_PID; 
    } 
    else 
    { 
     // OS level getpid() function 
    } 
} 

Как я могу назвать реализацию оригинальной GETPID() ОС с помощью этой функции?

EDIT: Я пробовал:

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

Джонатан предложил. Это дало мне следующие ошибки при компиляции с г ++:

In function pid_t getpid()': SerendibPlugin.cpp:882: error: _getpid' undeclared (first use this function) SerendibPlugin.cpp:882: error: (Each undeclared identifier is reported only once for each function it appears in.)

EDIT 2: Мне удалось получить эту работу, используя указатель на функцию и установить его на следующий второй символ с идентификатором «GETPID», используя dlsym (RTLD_NEXT, «getpid»).

Вот мой пример кода:

vi xx.c 
"xx.c" 23 lines, 425 characters 
#include <sys/types.h> 
#include <unistd.h> 
#include <stdio.h> 
#include <iostream> 
#include <dlfcn.h> 

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

pid_t getpid(void) 
{ 
    cout << "My 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); 
} 

г ++ xx.c -o XOUT

My getpid 
PID :7802 
7802 
+2

Вы хотите переопределить эту функцию для любого другого приложения, которое ее вызывает? Для любви к Богу, почему? –

+0

Последняя. Мне хотелось бы сделать это по-другому, но нет. – Gayan

ответ

4

На многих системах, вы обнаружите, что getpid() является 'слабым символом' для _getpid(), который может вызываться вместо getpid().


Первая версия упомянутого ответа __getpid(); упоминание было быстро устранено, поскольку оно было ошибочным.

Этот код работает для меня на Solaris 10 (SPARC) - с C++ компилятор:

#include <sys/types.h> 
#include <unistd.h> 
#include <stdio.h> 

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); 
} 

Этот код работает для меня на Solaris 10 (SPARC) - с компилятором:

Black JL: cat xx.c 
#include <sys/types.h> 
#include <unistd.h> 
#include <stdio.h> 

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: 
+0

Я использую solaris 5.10. Я пробовал _getpid и __getpid, но оба возвращали ошибки. Мне может не хватать заголовочный файл. Я буду продолжать пытаться. – Gayan

+0

Образец, который вы предоставили компиляторам и отлично работает с cc и gcc, но не скомпилируется при использовании g ++. Любые указатели на то, как преодолеть это? – Gayan

+0

Интересно - какая версия g ++? Я тестировал с помощью g ++ 4.3.4 (4.4.0 все еще ожидающая сборка, библиотека pre-req играет на меня трюки), построенная для использования системного ассемблера и загрузчика. Какая у вас ошибка? –

0

Вы неправильно используете терминологию. Нельзя переопределять getpid(), потому что это не виртуальная функция. Все, что вы можете сделать, это попытаться заменить getpid другой функцией различными злыми средствами.

Но я должен спросить, почему вы это делаете? Замена getpid означает, что любой компонент, который был в зависимости от возврата getpid, теперь получит ваш предположительно измененный результат. Это изменение имеет очень высокий риск изменения какого-либо другого компонента.

Что вы предлагаете - это новая функциональность и, следовательно, должна быть другой функцией.

Если вы действительно хотите воспользоваться этим подходом, лучший способ - динамическая загрузка функции. Оригинальная DLL будет по-прежнему содержать функцию getpid, и вы можете получить доступ к ней с помощью комбинации LoadLibrary/GetProcAddress в Windows или dlopen/dlsym в Linux. Если вы используете другую ОС, укажите, пожалуйста.

EDIT В ответ на замечания, что GETPID должно быть проверяемым

Если тестирование является проблемой, то почему бы вместо того, чтобы не иметь пользовательские GETPID метод вы приложений. Например, applicationGetPid().Для нормального выполнения это может быть перенаправлено на системную функцию getpid. Но во время модульного тестирования он может использоваться для получения более предсказуемых значений.

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

Этот тип ovnerriding необходим, когда модульные тесты (в большой системе) делают что-то вроде генерации сообщений журнала с текущим PID в них. Таким образом, вы хотите, чтобы выход тестового блока (файлы журнала) был легко диффундирующим, поэтому вы хотите переопределить getpid(). Тем не менее, я согласен с предпосылкой просто сделать новую функцию и переключить весь код вызова. Это было бы самым простым в этом случае. – slacy

+0

Я согласен с тобой. Я исправлю вопрос. Мы пишем тестовый инструмент, который мог бы имитировать функциональность других процессов в системе. Некоторые из наших библиотек используют getpid, чтобы убедиться, что процесс действителен. Точная механика немного сложна, но я могу заверить вас, что мы приняли это решение после большого рассмотрения. – Gayan

+0

@slacy, в таком случае тогда вам лучше не помогать, создавая новую функцию, которая в обычном коде просто переходит к getpid. Но во время модульного теста оно составлено для более предсказуемой и проверяемой функции? Это более надежный подход, чем замена системных вызовов. – JaredPar

1

Вы можете использовать макрос:

в .h, включенный в каждый файл, где вы хотите заменить функцию getpid

#define getpid() mygetpid() 

Затем положить свою собственную реализацию в. cpp

pid_t mygetpid() { 
    // do what you want 
    return (getpid)(); 
} 
+0

Не будет ли это вызывать функцию mygetpid рекурсивно, так как getpid заменяется на определенное значение во время компиляции? – Gayan

+0

Хмм, я не думал в этом вопросе. .h должен быть включен во все файлы, где вы хотите, чтобы написать getpid, и не включать в .cpp, где вы определяете mygetpid. Компилятор должен сам найти реализацию mygetpid. –

Смежные вопросы