6

環境

GCC 4.6コンパイラを備えたLinuxシステム用に、C ++で特化したWebサーバーアプリケーションをゆっくりと作成しています(C onion httpサーバーライブラリとJSONシリアライゼーション用のJSONCPPライブラリを使用します)(移植性は気にしません)非 Linux システム、または 4.5 より前の GCC または 3.0 より前の Clang に)。

ユーザーの「データベース」 (ユーザーは非常に少なく、おそらく 1 人か 2 人なので、パフォーマンスは問題ではなく、O(n) アクセス時間は許容範囲内です) を JSON 形式で、おそらく JSON の小さな配列として保持することにしました。のようなオブジェクト

 { "_user" : "basile" ;
   "_crypasswd" : "XYZABC123" ; 
   "_email" : "basile@starynkevitch.net" ;
   "firstname" : "Basile" ;
   "lastname" : "Starynkevitch" ;
   "privileges" : "all" ;
 }

フィールドは名前でソルトされたユーザーパスワードのcrypt(3) "暗号化" であるという規則 (アラ.htpasswd) を使用します。_crypasswd_user

ユーザーを Json オブジェクトで記述したい理由は、私のアプリケーションが、ユーザーを記述する Json オブジェクトにいくつかの JSON フィールド (privileges上記など) を追加する (置き換えない) 可能性があるためです。C++ の Json 解析ライブラリとしてJsonCppを使用しています。このライブラリはifstreamを解析する必要があります。

だから私は自分のパスワードファイルを読んでいます

extern char* iaca_passwd_path; // the path of the password file
std::ifstream jsinpass(iaca_passwd_path);
Json::Value jpassarr;
Json::Reader reader;
reader.parse(jsinpass,jpassarr,true);
jsinpass.close();
assert (jpassarr.isArray());
for (int ix=0; ix<nbu; ix++) {
  const Json::Value&jcuruser= jpassarr[ix];
  assert(jcuruser.isObject());
  if (jcuruser["_user"].compare(user) == 0) {
    std::string crypasswd = jcuruser["_crypasswd"].asString();
    if (crypasswd.compare(crypted_password(user,password)) == 0) {
         // good user
    }
  }
}

質問

明らかに、 1 つのプロセスだけが読み取りまたは書き込みを行っていることを確認するために、パスワード ファイルflockを変更したいと考えています。lockfこれらの関数を呼び出すには、ifstream jsinpass. しかし、Google はほとんどがKreckel の fileno (完全だと思いますが、少し正気ではstd::ifstreamありません) を提供して、ファイル記述子を取得します。コンストラクターがその一部を事前に読み取らないかどうかはわかりません。したがって、私の質問:

ifstreamC++ (Linux、GCC 4.6)をロックするにはどうすればよいですか?

(または、その問題に取り組む他の方法を見つけましたか?)

ありがとう

4

4 に答える 4

1

から記述子を取得しようとするのではなく、別のロックファイルを使用することをお勧めしますifstreamifstream実装ははるかに簡単で、おそらくこれを自動化するクラスでラップできます。

アトミックなオープン/ロックを確実にしたい場合は、この SO answerで提案されている方法を使用してストリームを構築することをお勧めしますopenflock

于 2011-12-29T12:32:46.927 に答える
0

rename() の原子性に依存する従来の unix-y ソリューションは受け入れられませんか?

つまり、JSON シリアライゼーション形式がインプレース更新 (トランザクション ログなどを使用) をサポートしていない限り、パスワード データベースを更新するには、ファイル全体を書き換える必要がありますね。したがって、一時ファイルに書き込み、実際の名前で名前を変更して、読者が一貫したエントリを読み取れるようにすることもできますか? (もちろん、これが機能するためには、各リーダーが DB エントリにアクセスするたびにファイルを open() する必要があります。ファイルを開いたままにしても、それは切断されません)

于 2011-12-29T12:55:12.553 に答える