【问题标题】:Pipe + select: select never woken up管道 + 选择:选择从未唤醒
【发布时间】:2016-07-08 12:02:05
【问题描述】:

我正在构建一个小型 io 服务,用于检查某些 fd 的读写可用性。

为此,我有一个专门用于选择的线程,没有任何超时,因此只有在 fd 可用时才会唤醒选择。

但是,我有时想强制选择在特定事件时被唤醒。为此,我只需使用管道,观察它的读取可用性,并在我想唤醒 select 调用时在其上写入。

这在大多数情况下都有效,但有时当我写入管道时什么都没有发生。所以 select 调用会无限期地被阻塞。

这是我使用的部分代码:

选择线程:

FD_ZERO(&rd_set);
//! set some other fds...
FD_SET(m_notif_pipe_fds[0], &rd_set);
select(max_fd + 1, &rd_set, &wr_set, nullptr, nullptr);
if (FD_ISSET(m_notif_pipe_fds[0], &rd_set)) {
  char buf[1024];
  read(m_notif_pipe_fds[0], buf, 1024);
}

通知线程:

write(m_notif_pipe_fds[1], "a", 1);

max_fd 变量已有效地设置为最高 fd 值(不是要观察的 fd 数量,这是一个常见错误)。

有什么想法吗?

【问题讨论】:

  • 您确定您的选择线程被阻止在select 中而不是在read 中吗?
  • 是的,我在读取和选择前后添加了一些日志。
  • 你检查write的返回值了吗?

标签: c++ multithreading select pipe


【解决方案1】:

我建议你让你的管道不阻塞

int flags = fcntl(m_notif_pipe_fd[1], F_GETFL, 0);
assert(flags != -1);    
fcntl(m_notif_pipe_fd[1], F_SETFL, flags | O_NONBLOCK);

并将管道缓冲区大小设置为 1

int pipe_sz = fcntl(m_notif_pipe_fd[1], F_SETPIPE_SZ, 1);

this question

【讨论】:

  • 太棒了,正是我想要的,非常感谢!
猜你喜欢
  • 1970-01-01
  • 2013-05-29
  • 1970-01-01
  • 1970-01-01
  • 2017-04-26
  • 2018-09-22
  • 1970-01-01
  • 2014-01-24
  • 1970-01-01
相关资源
最近更新 更多