7

我正在使用非阻塞套接字 (C/C++) 和select. 这个程序很大,所以我不能上传源代码。在一个非常激进的测试会话中,我使用测试代码频繁地打开和关闭 TCP 和 UDP。它总是最终导致一端没有响应并且 CPU 使用率超过 98 或 99%。然后我使用gdb来附加。“bt”显示以下内容:

0x00007f1b71b59ac3 in __select_nocancel () at ../sysdeps/unix/syscall-template.S:82
82  ../sysdeps/unix/syscall-template.S: No such file or directory.
    in ../sysdeps/unix/syscall-template.S

可能是什么类型的错误?

$ uname -a
Linux kiosk2 2.6.32-34-generic #77-Ubuntu SMP Tue Sep 13 19:39:17 UTC 2011 x86_64 GNU/Linux
4

1 回答 1

44

不看代码就不可能说出来,但通常当基于选择的循环开始以约 100% 的 CPU 使用率旋转时,这是因为您告诉select()要监视的一个或多个套接字已准备好读取(和/或准备就绪) -for-write) 以便select()立即返回而不是阻塞......但是代码实际上忽略了recv()(或send())该套接字上的任何数据。在无法读取/写入任何内容后,您的事件循环将尝试通过再次调用回到睡眠状态select(),但当然套接字的数据(或缓冲区空间,在准备写入的情况下)仍然等待处理,所以select()再次立即返回,错误的代码忽略了再次读取(或write()),然后我们以最快的速度前进:)

另一种可能性是您传递的超时值select()为零或接近零,select()即使没有套接字准备好进行任何操作,也会导致非常快速地返回......当人们忘记重新初始化时经常发生这种情况每次调用select(). 您需要每次重新初始化 timeval 结构,因为某些实现select()会在返回之前对其进行修改。

我的建议是在您调用 之前和之后立即放置一些 printf(或您最喜欢的等价物),并在select()您重现故障时观察该输出。这将向您显示旋转是否发生在对 的单个调用中select(),或者是否导致某些事情select()一次又一次地立即返回。

于 2013-11-02T02:32:38.580 回答