如果与其他描述符一起使用,选择系统调用不会返回设置的标准输入

问题描述 投票:0回答:1
int main() {
  fd_set readfds;
  fd_set writefds;
  FD_ZERO(&readfds);
  FD_ZERO(&writefds);

  FD_SET(0, &readfds);
  int fd = open("random_path", O_WRONLY);
  FD_SET(fd, &writefds);

  struct timeval tv;
  tv.tv_sec = 10;
  tv.tv_usec = 0;

  int r = 0;
  string s;
  int i = 0;
  // Running loop 5 times
  while (i<5) {
    r = select(fd+1, &readfds, &writefds, NULL, &tv);
    cout<<"r is "<<r<<endl;
    if (r == -1) {
      cout<<"error"<<endl;
      exit(1);
    }
    if (FD_ISSET(0, &readfds)) {
      cout<<"reading from stdin"<<endl;
      cin>>s;
      cout<<"s is "<<s<<endl;
    }
    if (FD_ISSET(fd, &writefds)) {
      cout<<"writing to file"<<endl;
      write(fd, s.c_str(), s.length());
    }
    cout<<"sleeping"<<endl;
    sleep(5);
    i += 1;
  }
}

当我运行这个时,我得到的输出是

r is 1
writing to file
sleeping
random text to set stdin fd
r is 1
writing to file
sleeping

如您所见,代码永远不会进入 FD_ISSET(0, &readfds) ,因为它永远不会打印“从 stdin 读取”,但是,如果我将选择系统调用从 select(fd+1) 更改为 select(1 或 2),即小于 fd 的任何内容,然后我可以看到“从 stdin 读取”

qqq
r is 1
reading from stdin
s is qqq
sleeping
c++ linux io posix-select
1个回答
0
投票

必须在每次迭代时设置 fdset。每次调用 select() 时都会修改(销毁)所有 fdset,从而添加 FD_ZERO($readfds); FD_SET(0,&readfds);作为重新初始化的一部分,有效

© www.soinside.com 2019 - 2024. All rights reserved.