2

読み取ることができないfdsがたくさんあります(たとえば、リスニングソケット)。データを取り出すリスクを冒さずreadに、fdの(2)が返されるかどうかをテストするにはどうすればよいですか?EINVAL

動作しないもの:

  1. read()渡されたゼロバイトのバッファでを行うことができます。ただし、これは除外されます。

    read()実装は、ゼロバイトの要求に対してエラーチェックを実行することを許可されていますが、必須ではありません。[POSIX1003.1-2008から]

  2. select()記述子を呼び出したくなるかもしれません。残念ながら、select()読み取り可能なセットのセマンティクスは非常にオーバーロードされているため、実際にはfdを呼び出すとエラーが発生したときに、fdが「読み取り可能」であることがわかりますread()(たとえば、リスニングソケットは「読み取り可能」とマークされますが、、accept()ではなくread()、が必要です。イベントやkqueuefdsのような他の移植性のない例があります)。

  3. (作業の並べ替え)特定のシステムコールを使用してfdをテストし、コンパイルするすべてのプラットフォームのマンページを読んで、おおよそ次のような関数を生成します。

    int isReadable(int fd)
    { return isActiveSocket(fd) || isFifo(fd) || isRegFile(fd) ||
               isEventFd(fd) || ... /* more pain */ }
    
  4. (作品の並べ替え)read()fdがシステムコールに適切なタイプであったかどうかについて、それ自体が必ずしも良い答えを与えるとは限らないことに注意してください!驚いたことに、EINVALPOSIX for read()(STREAMSを除く)では指定されていませんが、Linux( "EINVAL:fdは読み取りに適さないオブジェクトにアタッチされています")ではなく、BSD( "EINVAL:に関連付けられたポインター[fd]は負でした。」)。

シナリオ

誰かがあなたのアプリケーションを起動し、あなたは値0のfdが偽物(例えばリスニングソケット)であるかどうか、またはそれから読み取ることが可能になるかどうかを知りたいと思っています。read()実際のa)ブロックするため、b)データを取り出した後、データを元に戻すことができないため、実際に試さずにやりたいと思います。

4

4 に答える 4

2

いいえ。仕様の関連部分を自分で引用しました。

実際、読み取りは、さまざまな理由でいつでも失敗する可能性があります。「読み取り成功」のテストに続いてread、競合状態が発生するだけです。2つの呼び出しの間に状況が変わる可能性があります。

失敗した読み取りが適切に処理されるようにアプリケーションを作成する必要があります。そうすれば、通常、事前にテストを行う必要はなく、selectデータが(おそらく)いつ利用可能になるかを判断するために使用できます。

于 2013-05-02T13:40:10.427 に答える
2

F_GETXFLオプションでfcntlを使用できない理由はありますか?

int isread(int fd)
{
   int o_accmode=0;
   int rc=fcntl(fd, F_GETXFL, &o_accmode);
   if(rc == -1 )
       return rc;
   rc=(o_accmode & O_ACCMODE);
   return (rc==O_RDONLY || rc==RDWR);
}
于 2013-05-02T16:10:21.360 に答える
1

おそらく最も簡単なのは使用することselectです:

int
is_valid_descriptor( int fd )
{
  fd_set rd;
  struct timeval t = { 0, 0 };
  FD_ZERO( &rd );
  FD_SET( fd, &rd );
  return -1 != select( fd + 1, &rd, NULL, NULL, &t );
}

これは、読み取りがブロックされるかどうかを示すものではないことに注意してください(「成功」の意味は明確ではありません)。

于 2013-03-08T21:09:40.267 に答える
1

read()の代わりにrecv()を呼び出しても問題ないと仮定すると(通常、ソケットと交換可能です)、flags引数でMSG_PEEKを指定でき、recv()呼び出しは、実際には削除されないことを除いて、通常どおりに機能します。ソケットの内部バッファからの任意のバイト。これを使用して、ソケットの内部状態を変更せずにエラーをキャッチできる場合があります。

于 2013-03-09T02:16:56.797 に答える