投票でこれらのビットを設定するときに何をすべきか疑問に思っていますか?ソケットを閉じて、無視しますか?
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/
最も簡単な方法は、どのような場合でもソケットが使用できなくなったと想定して、ソケットを閉じることです。
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
を設定し、ソケットの動作はより可変的です。
最小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");
}
}
}
_
コンパイル:
_gcc -o poll.out -std=c99 poll.c
_
使用法:
_Sudo mknod -m 666 poll0.tmp p
./poll.out
_
別のシェルで:
_printf a >poll0.tmp
_
[〜#〜] pollhup [〜#〜]
ソースを変更しない場合:_./poll.out
_出力:
_loop
POLLIN n=1 buf=a
loop
POLLHUP
loop
_
そう:
POLLIN
は、入力が利用可能になると発生しますPOLLHUP
は、ファイルがprintf
によって閉じられたときに発生しますclose(pfd.fd);
と_pfd.fd *= -1;
_がクリーンアップし、POLLHUP
の受信を停止しますpoll
が永久にハングしますこれは通常の操作です。
これで、FIFOで次のopen
を待つか、完了したらループを終了することができます。
[〜#〜] pollnal [〜#〜]
コメントアウトした場合_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でPOLLERR
を生成する方法がわかりません。方法があれば教えてください。しかし、デバイスドライバーの_file_operations
_で可能になるはずです。
Ubuntu 14.04でテスト済み。