尽管没有输入,为什么民意调查会继续返回?

bit*_*ask 5 c++ linux file-descriptor poll-syscall

我写了一个小测试程序来弄清楚如何交谈poll.我创建了三个文件testa,testb,testc和写入字符串hello\n到第一.所以,这是我的调用poll:

poll(polls.data(),polls.size(),-1)
Run Code Online (Sandbox Code Playgroud)

根据联机帮助页,超时-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";
        }
      }
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

我得到的是这个:

{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
Run Code Online (Sandbox Code Playgroud)

(永远重复最后两行)

我正在使用g++ -Wall -Wextra -std=c++11 poll.cpp -o poll3.10-2-amd64内核构建.

Pet*_*ter 6

常规文件中的EOF条件仍然可读.换句话说,你read()不会阻止.这里有一个很好的列表,列出了poll()不同类型文件描述符对EOF的不同实现:http://www.greenend.org.uk/rjk/tech/poll.html

请注意,常规文件始终返回POLLIN.所以你需要单独测试EOF.实际上,对常规文件进行轮询并不会对您有任何影响.您需要套接字或管道或其他东西来测试您的代码.

其他说明:您可能想要检查其他结果.revents.POLLERR,POLLHUP和POLLNVAL都发出不同的错误信号,需要特殊处理.