3

我有一个用 C 编写的守护程序应用程序,目前在 Solaris 10 机器上运行,没有已知问题。我正在将其移植到 Linux 上。我不得不做出最小的改变。在测试期间,它通过了所有测试用例。它的功能没有问题。但是,当我在 Solaris 机器上“空闲”时查看它的 CPU 使用率时,它使用了大约 0.03% 的 CPU。在运行 Red Hat Enterprise Linux 4.8 的虚拟机上,相同的进程使用所有可用的 CPU(通常在 90%+ 范围内)。

我的第一个想法是事件循环一定有问题。事件循环是一个无限循环 ( while(1)),调用select(). timeval 设置为timeval.tv_sec = 0timeval.tv_usec = 1000。对于该过程正在执行的操作,这似乎足够合理。作为一项测试,我将其timeval.tv_sec设置为 1。即使在这样做之后,我也看到了同样的问题。

关于 select 在 Linux 和 Unix 上的工作方式,我有什么遗漏吗?或者它与虚拟机上运行的操作系统有什么不同?或者也许还有其他我完全想念的东西?

还有一件事我不确定正在使用哪个版本的 vmware 服务器。虽然它是大约一个月前才更新的。

4

2 回答 2

5

我相信 Linux 通过将剩余时间写入 select() 调用的时间参数来返回剩余时间,而 Solaris 不会。这意味着不了解 POSIX 规范的程序员可能不会在调用 select 之间重置 time 参数。

这将导致第一次调用具有 1000 微秒超时,而所有其他调用使用 0 微秒超时。

于 2010-03-12T20:12:41.070 回答
1

正如 Zan Lynx 所说,timeval 在 linux 上由 select 修改,因此您应该在每次 select 调用之前重新分配正确的值。另外我建议检查某些文件描述符是否处于特定状态(例如文件结束,对等连接关闭......)。也许移植在返回值的分析中显示了一些潜在的错误(FD_ISSET 等)。几年前,在一个选择驱动循环的端口中,我也发生过这种情况:我以错误的方式使用返回的值,并且在 rd_set 中添加了一个封闭的 fd,导致选择失败。在旧平台上,错误的 fd 用于具有高于 maxfd 的值,因此被忽略。由于同样的错误,程序无法识别选择失败(select() == -1)并永远循环。

再见!

于 2010-03-12T20:30:08.300 回答