等待可读文件描述符和可写文件描述符

时间:2017-02-03 01:06:25

标签: linux select

我需要等待从文件描述符A读取的内容,然后只有在文件描述符B可写时才读取它。 我的第一个实现是这样的(Pseudocode):

while (true) {
  select(A readable, B writeable, timeout)
  if (A was readable and B was writeable) {
    ReadFromAWriteToB();
  }
}

这就产生了一个问题,即只要其中一个条件发生,就会返回选择。这是一个问题,因为A在10%的时间内是可读的,但B在90%的时间都是可写的,因此即使我们通常没有任何数据可以从A读取,它也会唤醒写入B.

我的下一个实现是这样的:

while (true) {
  select(A readableB, timeout);
  if (A was readable) {
    select(B writeable, 0); // Check if it is writeable right now
    if (B was writeable) {
      ReadFromAWriteToB();
    }
  }
}

这样更好,但是我得到了A可读的峰值,所以第一个选择直接返回,但是B不可写,所以我会进入一个繁忙的循环,直到B再次可写。

所以我可以在第二个选择中添加一个小等待,例如1毫秒。 我真正希望能够做的是选择/轮询,直到两个条件都有效,而不仅仅是一个或另一个,但我不认为select / poll支持这个。 是否有更好的API可供使用或更好的方法来构建此循环?

1 个答案:

答案 0 :(得分:2)

在发现B不可写之后如何添加睡眠?

while (true) {
  select(A readableB, timeout);
  if (A was readable) {
    select(B writeable, 0); // Check if it is writeable right now
    if (B was writeable) {
      ReadFromAWriteToB();
    }
    else {
      sleep for an appropriate amount of time
    }
  }
}

这将:

  • 在A准备好且B不在
  • 时防止紧密循环
  • 确保我们在检查B之前总是重新检查A

如果我们可以在找到A准备就绪后等待无限的时间,我们可以像这样重写循环:

while (true) {
  select(A readableB, timeout);
  if (A was readable) {
    b_timeout = 0
    while true {
      select(B writeable, b_timeout); // Check if it is writeable right now
      if (B was writeable) {
        ReadFromAWriteToB();
        break;
      }
      sleep for a small amount of time to prevent tight loop around B
      b_timeout += a few milli seconds
    }
  }
}

这将

  • 像前一个解决方案一样阻止紧密循环
  • 减少我们在找到A之后检查A的次数

希望这是有道理的。