web-dev-qa-db-ja.com

変数に格納されている特定のファイル記述子がまだ有効であるかどうかを確認するにはどうすればよいですか?

Varという変数にファイル記述子を保存しています。その記述子が後の段階で有効かどうかを確認するにはどうすればよいですか?

  fdvar1= open(.....);
  fdvar2 = fdvar1;       // Please ignore the bad design

  ....
  // lots of loops , conditionals and threads. It can call close(fdvar2) also.  
  ....

  if(CheckValid(fdvar1)) // How can I do this check  ?
    write(fdvar1, ....);

今、私はvar1(開いた記述子をまだ保持している)がまだ有効かどうかを確認したい。そのためのAPIはありますか?

43
Lunar Mushrooms

fcntl(fd, F_GETFD) は、fdが有効なオープンファイル記述子であることを確認するための標準的な最も安価な方法です。多数のバッチチェックが必要な場合は、タイムアウトがゼロのpollを使用し、eventsメンバーを0に設定し、POLLNVALreventsをチェックします。返される方が効率的です。

とはいえ、「特定のリソースハンドルがまだ有効かどうかを確認する」という操作は、ほとんどの場合基本的に正しくありません。リソースハンドルが解放された後(たとえば、fdがclosed)、その値は、次に割り当てるそのようなリソースに再割り当てされる場合があります。使用される可能性のある参照が残っている場合、古い参照ではなく新しいリソースで誤って動作します。したがって、本当の答えはおそらく次のとおりです。プログラムのロジックがまだわからない場合は、修正する必要がある主要な基本的なロジックエラーがあります。

73
R..

fcntl()関数を使用できます:

int fd_is_valid(int fd)
{
    return fcntl(fd, F_GETFD) != -1 || errno != EBADF;
}
23
user529758

記述子がまだ有効かどうかを通知できる関数はないと思います。記述子は通常6のような小さな整数であり、ファイルを閉じて後で新しいものを開く場合、libcはその番号を再利用することを選択できます。

代わりに、dup()を使用してファイル記述子をコピーすることを検討する必要があります。複数の場所で同じ記述子を使用する代わりにファイル記述子を複製することにより、ファイル記述子がまだ有効であるかどうかを確認しやすくなります。完了したら、元の記述子と複製された記述子の両方を閉じることを忘れないでください。

5
David Grayson

this フォーラムの記事から:

int is_valid_fd(int fd)
{
    return fcntl(fd, F_GETFL) != -1 || errno != EBADF;
}

fcntl(GETFL)は、おそらくファイル記述子に対して実行できる最も安価で失敗する可能性が最も低い操作です。特に、この仕様では、信号によって中断されることはなく、どこに保持されているロックの影響も受けないことが示唆されています。

4
wbao

まだ同じリソースを指しているかどうかを知りたい場合は、開いた直後に記述子をfstat()して、後でもう一度それを行うことができます(完全ではない)アプローチ結果を比較します。 _.st_mode_&_S_IFMT_を見て開始し、そこから先に進みます-ファイルシステムオブジェクトですか? _.st_dev / .st_ino._を見てください。ソケットですか? getsockname()getpeername()を試してください。 100%確実ではありませんが、間違いなく同じでないかどうかはわかります。

0
John Hascall