2

これが processabで、どちらもマルチスレッドです。

  1. a1 つの新しいプログラムをforkbし、bすぐに実行します。
  2. a dupログファイルへの s およびfreopens stderr (aデファクト Apache の httpd2.22 です)
  3. bから開かれた stderr を継承しaます。(私はapache httpdを適応させています、これbは私のプログラムです)、そしてロギングにb使用しますfprintf(stderr....)
  4. そのためabロギング用に同じファイルを共有します
  5. aには、bログを書き込むためのロック メカニズムはありません

一部のログ メッセージがインターリーブしていて、ログ メッセージの一部が失われていることがわかりました。

同じファイルへの 2 つのライターが暗黙的にお互いをロックアウトできますか?

より重要な問題はfprintf、1 つのマルチスレッド プロセス内でのみ使用する場合、fprintfスレッド セーフfprintfですかfprintf。多くの記事でこのように述べられていますが、これを自分で確認するのは簡単ではないので、ここで助けを求めます。

A: fd を複製するためのコードは次のようになります。

......
rv = apr_file_dup2(stderr_log, s_main->error_log, stderr_p);//dup the stderr to the logfile
apr_file_close(s_main->error_log);//here ,2 fd point to the same file description,so close one of 

それから

B:apache は、ロギングのためにこの方法を使用します。

......
if (rv != APR_SUCCESS) {
    ap_log_error(APLOG_MARK, APLOG_CRIT, rv, s_main, ".........");

C:便宜上、私はこの方法でログインしています:

fprintf(stderr,".....\n")

私はApacheと私がファイル書き込みに同じfdを使用していると確信しています。

4

1 に答える 1

8

開いているファイルに対して出力を実行するために単一のFILEオブジェクトを使用している場合、そのfprintf呼び出し全体がアトミックになります。つまり、呼び出しの間FILE、ロックが保持されます。aは単一プロセスのアドレス空間に対してローカルであるため、この設定はマルチスレッド アプリケーションでのみ可能です。いくつかの異なるプロセスが、同じ基礎となる開いているファイルを参照する個別のオブジェクトにアクセスしているマルチプロセス設定には適用されません。ここで使用している場合でも、各プロセスには独自のロックとロック解除があり、他のプロセスに変更が表示されないため、書き込みがインターリーブされる可能性があります。これを防ぐには、いくつかの方法があります。FILEfprintfFILEFILEfprintfFILE

  1. 共有メモリに同期オブジェクト (プロセス共有セマフォやミューテックスなど) を割り当て、ファイルに書き込む前に各プロセスがロックを取得するようにします (一度に 1 つのプロセスだけが書き込みできるようにします)。また

  2. fcntlロックや (非 POSIX) BSDflockインターフェイスなど、ファイルシステム レベルのアドバイザリ ロックを使用します。また

  3. ログ ファイルに直接書き込む代わりに、別のプロセスがログ ファイルにフィードするパイプに書き込みます。PIPE_BUFパイプへの書き込みは、バイト長よりも小さい限り、(POSIX により) アトミックであることが保証されます。この場合は使用できませんがfprintf(基礎となる複数の書き込み操作を実行する可能性があるため)、snprintf-sizePIPE_BUFのバッファーの後にwrite.

于 2012-07-26T07:51:57.087 に答える