read()
簡単な答えは、戻るEWOULDBLOCK
(または)まで読むかEAGAIN
、エラーでクラップスすることです。
使用しているオペレーティングシステム(またはランタイム)にバグがない限り、あなたが言っていることは単純に起こり得ません。そうでなければ、あなたは何か間違ったことをしているに違いありません。たとえば、select()
レベルトリガーI/Oを使用しています。ほとんどの場合、ソケットを完全に使い果たしていないのでselect()
、そこに何かが残っていることを常に示していると思います(これはエッジトリガーイベント通知では発生しません)。
read()
以下は、記述子が読み取り可能な状態のままになるのを避けるために、リターンまで読み取る方法を示す簡単な例ですEWOULDBLOCK
(OS Xでこれをコンパイルしてテストしましたが、エラーチェックもほとんどありませんが、アイデアを得る必要があります)::
/*
* FIFO example using select.
*
* $ mkfifo /tmp/fifo
* $ clang -Wall -o test ./test.c
* $ ./test &
* $ echo 'hello' > /tmp/fifo
* $ echo 'hello world' > /tmp/fifo
* $ killall test
*/
#include <sys/types.h>
#include <sys/select.h>
#include <errno.h>
#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
int main()
{
int fd;
int n;
fd_set set;
ssize_t bytes;
size_t total_bytes;
char buf[1024];
fd = open("/tmp/fifo", O_RDWR | O_NONBLOCK);
if (fd == -1) {
perror("open");
return EXIT_FAILURE;
}
FD_ZERO(&set);
FD_SET(fd, &set);
for (;;) {
n = select(fd+1, &set, NULL, NULL, NULL);
if (!n)
continue;
if (n == -1) {
perror("select");
return EXIT_FAILURE;
}
if (FD_ISSET(fd, &set)) {
printf("Descriptor %d is ready.\n", fd);
total_bytes = 0;
for (;;) {
bytes = read(fd, buf, sizeof(buf));
if (bytes > 0) {
total_bytes += (size_t)bytes;
} else {
if (errno == EWOULDBLOCK) {
/* Done reading */
printf("done reading (%lu bytes)\n", total_bytes);
break;
} else {
perror("read");
return EXIT_FAILURE;
}
}
}
}
}
return EXIT_SUCCESS;
}
基本的に、レベルトリガーI / Oは、以前に通知されていたとしても、何か読むものがある場合は常に通知を受け取ることを意味します。逆に、エッジトリガーI / Oは、新しいデータが到着するたびに1回だけ通知を受け取ることを意味し、データを読み取るかどうかは関係ありません。select()
レベルトリガーI/Oインターフェイスです。
それが役に立てば幸い。幸運を!