1

成長したアプリケーションに、fork(2)とexec(3)(現在はexecl)を使って別のアプリケーションの実行を開始する新機能を追加したいと考えています。

残念ながら、アプリケーションは共有メモリ、共有セマフォを使用し、膨大な数の開いているファイル記述子を持っています。これらは fork を呼び出すときにすべて複製されます。子プロセスで execl を呼び出す前に、すべてのファイル記述子、共有リソースなどを閉じる必要があることはわかっていますが、これらの一部はサードパーティのライブラリによって処理され、アクセスする手段がありません。

さらに、アプリケーションはすべてスレッド化されています (posix スレッドを使用) が、子プロセスの fork と exec の間に非同期システム コールがない限り問題ありません ( http://www.linuxprogrammingblog.com/threadsによると)。 -and-fork-think-twice-before-using-them )。

私が今直面している問題は、execl 呼び出しが何らかの形で共有リソースを破損しているように見え、それらを使用するスレッドでデッドロックが発生することです。これは、_exit (2) を使用して fork した直後に子プロセスを終了するように execl を呼び出しても、この動作が発生しない場合にのみ発生するようです。

fork と exec で新しいプロセスを生成するときに、共有メモリと共有セマフォを処理する適切な方法は何ですか?

4

3 に答える 3

1

ほとんどの場合、デッドロックは子のファイル記述子を閉じないことから発生します。他の何かを試す前に、これを試してください:

子内のすべてのファイル記述子を反復処理し、/proc/[pid]/fdを呼び出す前にそれらを閉じますexec

これがうまくいかない場合は、(スタックフレームを除く)すべてのメモリを。のようにマークする必要がありMADV_DONTFORKますmadvise/proc/[pid]/mapsマッピング範囲をローカルスレッドスタック上の任意のポインタと比較することにより、ローカルスタックフレームから現在のすべてのマップのリストを取得できます。

于 2012-11-07T01:41:13.497 に答える
1

ここでは、fork() および exec() コードのバグや、プログラムが共有メモリとセマフォを使用する方法のバグなど、複数の問題が発生している可能性があります。

これを処理する 1 つの可能な方法は、system()関数を使用することです。

これにより、シェル環境でコマンドが実行され、プログラムが終了するまでブロックされます。新しいスレッドを生成してから、system. 組み込み関数が適切な fork() および exec() を処理できるようにします。

それでも問題が解決しない場合は、共有メモリ/セマフォが fork および exec と互換性がないと言えます。

于 2012-11-06T20:22:30.900 に答える
1

ここでも、すべてのファイル記述子を閉じるために現在使用しているコードを示します (コメントでは見栄えがよくありません)。

    DIR* hdir = opendir("/proc/self/fd/");
    struct dirent* entry;
    int fd;

    if (hdir != NULL) {
        while ((entry = readdir(hdir)) != NULL) {
            fd = strtol(entry->d_name, NULL, 10);

            if (fd > 2)
                close(fd);
        }

        closedir(hdir);
    }

これにより、1ダースのファイル記述子が閉じられました。

于 2012-11-07T11:00:09.570 に答える