2009-04-28 6 views
2

私は、OSの元のものと置き換えるために新しいgetpid関数を書く必要があるアプリケーションがあります。実装は次のようになります。getpidを自分の実装に置き換える

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

どのように私はこの機能によりOSの元GETPID()の実装を呼び出すことができますか?

編集:私が試した:ジョナサンなど

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」idの次の2番目のシンボルに設定することで仕事を得ることができました、 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)に私の作品 - Cコンパイラで:

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関数が含まれており、WindowsではLoadLibrary/GetProcAddress、Linuxではdlopen/dlsymの組み合わせでアクセスできます。別のOSを使用している場合は、指定してください。テストが懸念される場合は、なぜあなたの代わりにしているアプリケーションのカスタムGETPID方法を持っていないテスト可能

するニーズをGETPIDコメントへの対応

EDIT。たとえば、applicationGetPid()などです。通常の実行では、これをシステムのgetpid関数に転送することができます。しかし、ユニットテスト中に、より予測可能な値を生成するために使用することができます。

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

ユニットテスト(大規模システムで)が現在のPIDを持つログメッセージを生成するようなことを行う場合、このようなオーバーライドが必要です。したがって、単体テスト出力(ログファイル)を簡単にdiffableにしたいので、getpid()をオーバーライドする必要があります。 私は、新しい機能を作り、すべての呼び出しコードを切り替えるという前提に同意します。この場合、これは最も簡単です。 – slacy

+0

私はあなたに同意します。私はその問題を訂正します。 システム内の他のプロセスの機能をシミュレートできるテストツールを作成しています。いくつかのライブラリは、プロセスが有効かどうかを確認するためにgetpidを使用しています。正確な仕組みはちょっと複雑ですが、私たちはたくさんの配慮をしてこの決定を下したことを保証することができます。 – Gayan

+0

@slacy、その場合、通常のコードでは単にgetpidに転送する新しい関数を作成するほうがよいでしょう。しかし、単体テストでは、より予測可能でテスト可能な関数にコンパイルされていますか?これはシステムコールを置き換えるよりも信頼性の高いアプローチです。 – JaredPar

1

あなたがマクロを使用することができます:あなたは、その後getpid機能に

#define getpid() mygetpid() 

を交換して独自の実装を配置する場所の.hで

、すべてのファイルに含まれています。 cpp

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

コンパイル時にgetpidが定義された値に置き換えられるので、これはmygetpid関数を再帰的に呼び出しませんか? – Gayan

+0

ハム、私はこの時点では考えなかった。 .hは、getpidを書く上で必要なすべてのファイルに含まれ、mygetpidを定義する.cppには含まれません。リンカーは自分自身でmygetpidの実装を見つけるべきです。 –