select函数导致CPU使用率100%的问题

问题

项目重构过程中,发现修改后,进程的CPU始终为100%,相关代码如下:

    struct timeval timeout = {2,0};    
    while(1) 
    { 	
       result = select(FD_SETSIZE, &testfds, (fd_set *)0, (fd_set *)0, &timeout); 
    } 

分析

从代码上看,没有发现很明显的问题,使用gdb调试,发现select语句执行完后,timeout的值被修改为全0,下一次再执行时,相当于没有阻塞,立即返回,从而导致CPU利用率飙升到100%

查看select帮助文档,说明如下:

The timeout
The time structures involved are defined in and look like

Some code calls select() with all three sets empty, nfds zero, and a non-NULL timeout as a fairly portable way to sleep with subsecond precision.

On Linux, select() modifies timeout to reflect the amount of time not slept; most other implementations do not do this. (POSIX.1 permits either behavior.) This causes problems both when Linux code which reads timeout is ported to other operating systems, and when code is ported to Linux that reuses a struct timeval for multiple select()s in a loop without reinitializing it.
Consider timeout to be undefined after select() returns.

文档提到了timeout参数的用法,可以传入全0、NULL或者是设定的timeout参数,如果值是全0,select会立即返回,如果值是NULL,select会一直阻塞只到有数据到来,如果是设定值,最多会等待设定的时间。

需要特别注意的是,select调用完后,timeout的值可能被修改,是一个不确定的值。在上面的示例代码下,timeout编程了全0,从而导致了CPU使用率到100%的问题。

解决办法

每次调用select前,都对timeout显式赋值,正确代码如下:

    struct timeval timeout = {2,0};    
    while(1) 
    { 	
       timeout.tv_sec = 2;
       timeout.tv_usec = 0;
       result = select(FD_SETSIZE, &testfds, (fd_set *)0, (fd_set *)0, &timeout); 
    } 

select是一种比较传统的多路IO监听方法,效率不是很高,建议使用epoll来实现多路IO监听的功能。

你可能感兴趣的:(select函数导致CPU使用率100%的问题)