使用如此多CPU功率的select()有什么问题?

use*_*574 6 sockets tcp posix-select

我正在使用非阻塞套接字(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
Run Code Online (Sandbox Code Playgroud)

它可能是什么类型的错误?

$ uname -a
Linux kiosk2 2.6.32-34-generic #77-Ubuntu SMP Tue Sep 13 19:39:17 UTC 2011 x86_64 GNU/Linux
Run Code Online (Sandbox Code Playgroud)

Jer*_*ner 34

没有看代码就不可能说,但是当基于选择的循环开始以~100%的CPU使用率开始旋转时,这是因为你被告知select()要观看的一个或多个套接字是可以读取的(和/或准备好的) -for-write)这样就可以立即select()返回而不是阻塞......但是代码忽略了实际recv()(或send())该套接字上的任何数据.在无法读取/写入任何内容之后,您的事件循环将尝试通过select()再次调用返回休眠状态,但当然套接字的数据(或缓冲区空间,在准备写入的情况下)仍然在那里等待处理,所以select()马上再次返回,有缺陷的代码忽略了write()再次读取(或),并且我们周围的速度最快:)

另一种可能性是你传递一个超时值select()为零或接近于零,导致select()即使没有套接字准备好任何东西也能很快返回...这通常发生在人们忘记重新初始化时每次调用之前的timeval结构select().您需要每次重新初始化timeval结构,因为某些实现select()将在返回之前修改它.

我的建议是在你打电话之前和之后立即放一些printf(或你最喜欢的等价物)select(),并在重现故障时观察输出.这将显示旋转是在一次调用中发生的select(),还是某些东西导致select()一次又一次地返回.

  • 当问题中没有源代码时,我已经看到了最好的答案之一 (4认同)