Я написал небольшую тестовую программу, чтобы выяснить, как разговаривать с poll
. Я создал три файла testa
,testb
,testc
и написал строку hello\n
к первому. Итак, вот мой призыв poll
:
poll(polls.data(),polls.size(),-1)
Согласно manpage, время ожидания -1
должен указывать, что системный вызов никогда не прерывается. Тем не менее, он продолжает возвращаться, не имея ничего читать. Я всегда потребляю один байт ввода и вижу hello\n
печатается, но опрос не останавливается там. Он просто продолжает притворяться, что есть что почитать.
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/fcntl.h>
#include <sys/poll.h>
#include <unistd.h>
#include <errno.h>
#include <vector>
#include <map>
#include <string>
#include <iostream>
typedef int fd_t;
int main() {
fd_t const a = open("testa",O_RDONLY);
fd_t const b = open("testb",O_WRONLY);
fd_t const c = open("testc",O_RDWR);
std::map<fd_t,std::string> names{{{a,"testa"},{b,"testb"},{c,"testc"}}};
std::vector<pollfd> polls;
polls.push_back(pollfd{a, POLLIN, 0});
polls.push_back(pollfd{b, 0, 0});
polls.push_back(pollfd{c, POLLIN, 0});
while (poll(polls.data(),polls.size(),-1)) {
for (auto p : polls) {
if ((p.revents & (POLLIN|POLLERR)) == POLLIN) {
std::cout << "{" << p.fd << ", " << p.events << ", " << p.revents << "} ";
char byte;
auto const rr = read(p.fd,&byte,1);
auto const en = errno;
if (rr) {
std::cout << "File " << names[p.fd] << " says something: '" << ((int)byte) << " (" << (((' '<byte) && (byte<127))?byte:'\0') << ")" << "' \n";
} else {
std::cout << "Strange (file " << names[p.fd] << "). errno says " << en << "\n";
}
}
}
}
}
Что я получаю, это:
{3, 1, 1} File testa says something: '104 (h)'
{5, 1, 1} Strange (file testc). errno says 0
{3, 1, 1} File testa says something: '101 (e)'
{5, 1, 1} Strange (file testc). errno says 0
{3, 1, 1} File testa says something: '108 (l)'
{5, 1, 1} Strange (file testc). errno says 0
{3, 1, 1} File testa says something: '108 (l)'
{5, 1, 1} Strange (file testc). errno says 0
{3, 1, 1} File testa says something: '111 (o)'
{5, 1, 1} Strange (file testc). errno says 0
{3, 1, 1} File testa says something: '10 ()'
{5, 1, 1} Strange (file testc). errno says 0
{3, 1, 1} Strange (file testa). errno says 0
{5, 1, 1} Strange (file testc). errno says 0
{3, 1, 1} Strange (file testa). errno says 0
{5, 1, 1} Strange (file testc). errno says 0
{3, 1, 1} Strange (file testa). errno says 0
{5, 1, 1} Strange (file testc). errno says 0
{3, 1, 1} Strange (file testa). errno says 0
{5, 1, 1} Strange (file testc). errno says 0
(повторяет последние две строки навсегда)
Я строю с g++ -Wall -Wextra -std=c++11 poll.cpp -o poll
в ядре 3.10-2-amd64.
Условие EOF в обычном файле все еще доступно для чтения. Другими словами, ваш read()
не будет блокировать Вот хороший список того, как разные реализации poll()
реагировать на EOF в разных видах файловых дескрипторов: http://www.greenend.org.uk/rjk/tech/poll.html
Обратите внимание, что обычные файлы всегда возвращают POLLIN. Так что вам нужно проверить на EOF отдельно. На самом деле, опрос по обычному файлу ничего не делает для вас. Вам понадобятся сокеты или каналы или что-то еще, чтобы проверить ваш код.
Другие примечания: вы, вероятно, хотите проверить другие результаты в .revents
, POLLERR, POLLHUP и POLLNVAL сигнализируют о различных состояниях ошибки и требуют специальной обработки.
Локальные файловые дескрипторы всегда готовы к выполнению операций ввода-вывода (в отличие от сокетов, поскольку они зависят от внутреннего буфера ядра для ввода-вывода)). В вашем случае файловые дескрипторы всегда готовы к чтению, даже если они на самом деле пусты.
Как только вы достигаете конца файла, он остается читаемым, так что poll
вернется сразу, и звонит read
немедленно вернет ноль. Вы должны справиться с этим условием, возможно, закрыв его и удалив из набора опросов, где вы сейчас печатаете Strange
,