7

バックグラウンド

私はCで共有ライブラリを作成しており、動的にリンクされています。これは、、、、などのLD_PRELOADプリロードされたアプリケーションからのネットワーク呼び出しをインターセプトしてオーバーライドすることを目的としています。socket()connect()recv()send()

ライブラリの初期化で、。を使用してスレッドを起動しますpthread_create()。このスレッドは、ユーザースペースにマップされているカーネルメモリをポーリングします。

ライブラリは、 netperfiperfsockperfなどのネットワーキングベンチマークアプリケーションを処理するのに十分な汎用性を備えていますが、これらに限定されません。

私の問題

すべてがうまく機能し、1つを除いてほとんどの場合人生は甘いです。デーモン化されたアプリケーション。たとえば、netserver ( netperfベンチマークアプリケーションのサーバー側)をデーモンとして、つまり-Dパラメーターなしで起動した場合、アプリケーションが最初に行うことの1つはを呼び出すことfork()です。フォークでは、親はを使用exit(EXIT_SUCCESS)して閉じられ、子は接続をリッスンします。親が終了するという事実は私のポーリングスレッドを殺します。

ですから、私が達成したいのは、親がいなくなった場合に、子に新しいポーリングスレッドを生成させることです。通話を傍受して無効にすることはできますfork()が、基本的に、親が行ったかどうかを子供に知らせるにはどうすればよいですか?ライブラリは汎用でなければならないので、私は何の仮定もできません。

ありがとう。

4

3 に答える 3

5

getppid()関数を定期的にポーリングできます。'1'(initプロセスのID)を返し始めるとすぐに、親は死んでしまいます。

アップデート

'man pthread_create'からの抜粋:

新しいスレッドは、次のいずれかの方法で終了します。..。

  • プロセス内のスレッドのいずれかがexit(3)を呼び出すか、メインスレッドがmain()からの戻りを実行します。これにより、プロセス内のすべてのスレッドが終了します。

したがって、スレッドがexitを呼び出すネットサーバープロセスによって作成された場合-はい、このスレッドは終了します

于 2012-09-22T01:18:05.727 に答える
1

ptread_atfork(3)子でスレッドを起動するために使用できます。

于 2012-09-22T01:30:52.720 に答える
1

約1年後、私自身の質問に対する答えがあります。それは、「子プロセスは、親が死んでいることをどのようにして知るのか」というものでした。

さて、子供はを使用して、その親のPIDが何であるかを尋ねることができますgetppid()。親PIDが1の場合、子プロセスがプロセスに再ペアレント化されたことを意味しinitます。したがって、親は去りました。

例えば:

void child_fork(void)
{
    int parent_pid;
    usleep(1);
    parent_pid = (int)getppid();

    if (parent_pid == 1)
        run_my_polling_thread();
}

注:プロセスがフォークすると、親はスリープ状態になります。子プロセスが最初に実行され、次に親がウェイクアップされます(コピーオンライトの最適化については、ここでは詳しく説明しません)。usleep(1)親が目を覚まして終了する時間を持てるように、子供をすぐに眠らせるための呼びかけがここにあります。子供が目を覚ます前に、に親が変更されinitます。

さて、lib init時に、私はただ呼び出す必要があります:

__register_atfork(NULL, NULL, child_fork, NULL)

ただし、このソリューションはすべてのケースを網羅しているわけではありません。たとえば、親に複数の子がある場合はどうなりますか?本当に彼ら全員にポーリングスレッドを起動させたいですか?

理想的ではありませんが、今のところそれは私にとって許容できる解決策です。

于 2013-08-06T18:18:31.800 に答える