POLLNVAL
ファイル記述子の値が無効であることを意味します。通常はプログラムのエラーを示しますが、poll
に頼ることができます POLLNVAL
を返す ファイル記述子を閉じて、それ以降ファイルを開いていない場合、記述子を再利用した可能性があります。
POLLERR
select
からのエラー イベントに似ています . read
であることを示します または write
呼び出しはエラー状態 (I/O エラーなど) を返します。これには、select
の帯域外データは含まれません。 errorfds
経由で信号を送る マスクしますが poll
POLLPRI
経由のシグナル .
POLLHUP
基本的に、接続のもう一方の端にあるものが接続の端を閉じたことを意味します。 POSIX では
デバイスが切断されました。このイベントと POLLOUT は相互に排他的です。ハングアップが発生した場合、ストリームを書き込み可能にすることはできません。
これは端末にとって十分明らかです:端末がなくなった (SIGHUP を生成する同じイベント:モデム セッションが終了した、端末エミュレータ ウィンドウが閉じられたなど)。 POLLHUP
通常のファイルに対して送信されることはありません。パイプとソケットの場合は、オペレーティング システムによって異なります。 Linux は POLLHUP
を設定します パイプの書き込み側のプログラムがパイプを閉じ、POLLIN|POLLHUP
を設定したとき ソケットのもう一方の端がソケットを閉じたが、POLLIN
ソケットのシャットダウンの場合のみ。最近の *BSD セット POLLIN|POLLUP
パイプの書き込み側がパイプを閉じ、ソケットの動作がより可変になる場合。
POLLHUP
ソケットが接続されていないことを意味します。 TCP では、これは FIN が送受信されたことを意味します。
POLLERR
ソケットで非同期エラーが発生したことを意味します。 TCP では、これは通常、RST が受信または送信されたことを意味します。ファイル記述子がソケットでない場合、POLLERR
デバイスがポーリングをサポートしていない可能性があります。
上記の両方の条件で、ソケット ファイル記述子はまだ開いており、まだ閉じられていません (しかし shutdown()
既に呼び出されている可能性があります)。 close()
ファイル記述子で、ソケットに代わってまだ予約されているリソースを解放します。理論的には、ソケットをすぐに再利用できるはずです (たとえば、別の connect()
呼び出します)
POLLNVAL
ソケットファイル記述子が開いていないことを意味します。 close()
にするとエラーになります
それは正確なエラーの性質に依存します。 getsockopt() を使用して問題を確認してください:
int error = 0;
socklen_t errlen = sizeof(error);
getsockopt(fd, SOL_SOCKET, SO_ERROR, (void *)&error, &errlen);
値:http://www.xinotes.net/notes/note/1793/
最も簡単な方法は、ソケットがいずれにしても使用できなくなったと想定して閉じることです。
最小限の FIFO の例
これらの状況がいつ発生するかを理解すれば、対処法も簡単にわかるはずです。
poll.c
#define _XOPEN_SOURCE 700
#include <fcntl.h> /* creat, O_CREAT */
#include <poll.h> /* poll */
#include <stdio.h> /* printf, puts, snprintf */
#include <stdlib.h> /* EXIT_FAILURE, EXIT_SUCCESS */
#include <unistd.h> /* read */
int main(void) {
char buf[1024];
int fd, n;
short revents;
struct pollfd pfd;
fd = open("poll0.tmp", O_RDONLY | O_NONBLOCK);
pfd.fd = fd;
pfd.events = POLLIN;
while (1) {
puts("loop");
poll(&pfd, 1, -1);
revents = pfd.revents;
if (revents & POLLIN) {
n = read(pfd.fd, buf, sizeof(buf));
printf("POLLIN n=%d buf=%.*s\n", n, n, buf);
}
if (revents & POLLHUP) {
printf("POLLHUP\n");
close(pfd.fd);
pfd.fd *= -1;
}
if (revents & POLLNVAL) {
printf("POLLNVAL\n");
}
if (revents & POLLERR) {
printf("POLLERR\n");
}
}
}
GitHub アップストリーム。
コンパイル:
gcc -o poll.out -std=c99 poll.c
使い方:
sudo mknod -m 666 poll0.tmp p
./poll.out
別のシェル:
printf a >poll0.tmp
ポルハップ
ソースを変更しない場合:./poll.out
出力:
loop
POLLIN n=1 buf=a
loop
POLLHUP
loop
そう:
POLLIN
入力が利用可能になったときに発生POLLHUP
ファイルがprintf
によって閉じられたときに発生しますclose(pfd.fd);
とpfd.fd *= -1;
クリーンアップすると、POLLHUP
の受信が停止しますpoll
永久にハングアップ
これは通常の操作です。
次の open
を待つために FIFO を再登録できるようになりました。 、または完了したらループを終了します。
世論調査
pfd.fd *= -1;
をコメントアウトすると :./poll.out
プリント:
POLLIN n=1 buf=a
loop
POLLHUP
loop
POLLNVAL
loop
POLLNVAL
...
永遠にループします。
そう:
POLLIN
とPOLLHUP
とclose
以前のように起こったpfd.fd
を設定していないため 負の数poll
fd
を使用しようとし続けます- これは
POLLNVAL
を返し続けます 永遠に
したがって、これは発生すべきではなかったことがわかり、コードにバグがあることを示しています。
ポーラー
POLLERR
を生成する方法がわかりません FIFOで。方法があれば教えてください。しかし、file_operations
で可能なはずです
Ubuntu 14.04 でテスト済み。