g_io_channel 和 FIFO 导致 CPU 与 100% 挂钩

g_io_channel and FIFO causes CPU to peg to 100%

我想了解为什么当我将 FIFO 与 g_io_channel 结合使用时,我的 CPU 固定为 100%。

我在 github 上有一个项目用尽可能小的设置演示了这个问题;只是一个在 /tmp 中打开 FIFO 的简单服务器,以及一个通过该 FIFO 向服务器发送消息的客户端。

我发现:

  1. 第一次启动时,服务器占用接近于零CPU
  2. 客户端一通过FIFO向服务器发送消息,消息就被服务器接收并打印出来,然后CPU就到了100%。
  3. 您可以继续通过 FIFO 发送消息,服务器将打印它们,但 CPU 保持在 100% :-/

我已经尝试了通常的 google 和堆栈溢出,但到目前为止还没有找到解决方案。我希望有人能帮助我理解发生了什么。我相信我使用 glib/GTK 是正确的,但我很乐意接受纠正。感谢您提供的任何帮助。谢谢!

通过 运行 服务器使用 strace,我看到它只是在返回 POLLHUP 事件时循环调用 poll()。问题似乎是您希望能够无限期地等待 G_IO_IN 事件,告诉您数据即将到来,但不要管理告诉您连接已关闭的 G_IO_HUP

然后我在 bluez code 中找到了这条评论:

if (cond & (G_IO_ERR | G_IO_HUP)) {
        /*
         * Both ends needs to be open simultaneously before proceeding
         * any input or output operation. When the remote closes the
         * channel, hup signal is received on this end.
         */
        fifo_open();
        return FALSE;
}

这个 SO 问题解释了一切:Poll() on Named Pipe returns with POLLHUP constantly and immediately

这就是我在 strace 中看到的情况:当客户端进程退出时(您的进程或只是一个简单的 echo 到您的 fifo),IO 通道会收到连接另一端的通知吊起来。您的客户端当前发送一条消息并关闭连接。所以要么你想让它保持连接不断开,要么你需要重新打开 fifo 服务器端并添加一个新的手表,或者像我链接的 SO 问题中的 mark4o 所说的那样,you open the fifo with read/write rights server-side 这样你总是在 fifo(服务器)上至少有一个写入器,避免挂断。

例如,我链接到的 bluez 代码会关闭频道并在断开连接时打开一个新频道。还要小心处理代码中的引用计数问题。