1

ファイル記述子がスレッド間で共有されているため、プログラムにいくつかのスレッドがあるとします。 を呼び出すとclose(stderr)、すべてのスレッドが に出力されませんstderrstderr私の質問: あるスレッドの出力をシャットダウンする方法はありますか?

より具体的に言うと、プログラムの 1 つのスレッドがサードパーティのライブラリ関数を呼び出し、役に立たないとわかっている警告メッセージを出力し続けます。しかし、私はこのサードパーティ ライブラリ ソースにアクセスできません。

4

3 に答える 3

3

いいえ。ファイル記述子は、プロセス内のすべてのスレッドで使用できるグローバル リソースです。もちろん、標準エラーはファイル記述子番号 2 であるため、これはグローバル リソースであり、サード パーティ コードによる書き込みを停止することはできません。

問題が治療を正当化するほど深刻な場合は、次のことができます。

int fd2_copy = dup(2);
int fd2_null = open("/dev/null", O_WRONLY);

サードパーティ ライブラリ関数を呼び出す前に:

dup2(fd2_null, 2);
third_party_library_function();
dup2(fd2_copy, 2);

基本的に、サードパーティ ライブラリの期間中は、標準エラーを に切り替え/dev/nullて、関数の後に通常の出力を復元します。

もちろん、システム コールのエラー チェックを行う必要があります。

これの欠点は、このスレッドがサードパーティの関数を実行している間、標準エラーに書き込む必要がある他のスレッドも に書き込むこと/dev/nullです。

おそらく、「サードパーティ ライブラリ実行スレッド」(TPLET) と同期できる「エラー書き込みスレッド」(EWT) を追加するという観点から考える必要があります。他のスレッドは EWT にメッセージを書き込みます。TPLET がサードパーティ ライブラリを実行していた場合、EWT はそれが完了するまで待機し、キューに入れられたメッセージを書き込むだけでした。 (それは「うまくいく」でしょうが、大変な作業です。)

fd2_copyこれを回避する 1 つの方法は、標準エラー自体ではなく、一般的なコード (サードパーティ ライブラリ コード以外) で使用されるエラー報告関数を書き込むことです。これには、エラー報告関数を規則正しく使用する必要がありますが、スレッドを追加するよりもはるかに簡単です。

于 2013-05-30T07:03:24.183 に答える
2

Linux では、で宣言されている関数を使用して、現在のスレッドに独自のプライベート ファイル記述子テーブルを与えることできます。unshare()<sched.h>

unshare(CLONE_FILES);

その呼び出しの後、呼び出すことができclose(2);、現在のスレッドにのみ影響します。

ただし、ファイル記述子テーブルの共有が解除されると、再び共有に戻ることはできません。これは一方通行の操作です。これも Linux 固有であるため、移植性はありません。

于 2013-05-30T07:38:17.883 に答える
2

stderrスレッドごとではなくプロセスごとであるため、閉じるとすべてのスレッドが閉じます。

特定のメッセージをスキップしたい場合は、 を使用できますgrep -v

于 2013-05-30T07:04:51.223 に答える