程序的效率问题

各位大侠,现在有个问题请教,我现在在编写一个SOCKET网络通信程序,程序是双向的,定时读取对端的数据,然后将本地的数据发送过去,做了一个循环,大概象下面这个样子

while(1)
{
recv(…);
send(…);
usleep(10);
}

现在发现当有多个进程同时跑时CPU占有率很高,是不是这种轮询的方式很耗费CPU呢?同时sleep()的时间也很难控制,有没有别的方法来提高程序的效率呢?
recv()和send()函数如果设置成阻塞模式然后去掉sleep()是不是会有所提高呢?但是如果那样又会有一个问题是如果收不到或发不出去程序将锁住,不知我有没有说明白,请指教。

急等答案

最好能说清楚一点你的问题。简单来说:

定时读取的话,可以用定时器timer_create()。时间到系统给你通知。你再执行相应操作。比用usleep准确。并且误差不会积累。

还有timer_timeout(), Set a timeout on a blocking state
当你使用BLOCK的函数,但又不想永远被BLOCK的时候,就是你提到的情况了。可以考虑。Always call timer_timeout() just before the function that you wish to timeout. For example:


event.sigev_notify = SIGEV_UNBLOCK;

timeout.tv_sec = 10;
timeout.tv_nsec = 0;

timer_timeout( CLOCK_REALTIME, _NTO_TIMEOUT_SEND | _NTO_TIMEOUT_REPLY, &event, &timeout, NULL );
send( … );



还有select()也很好用。但不是定时读。是有数据的时候才读。
可以在对方有数据的时候才RECV,然后SEND。没有就BLOCK等待,不浪费CPU。并可同时指定TIMEOUT时间。如一分钟都没有收到数据,可以返回去做点别的事情。再重新等待数据。


根据你的情况选择,或配合来使用吧。

select()的使用麻烦大侠给个例子,另外我现在用的是non blocking,如果设置成block怎么判断管道断开呢?我希望不使用sleep以提高程序效率

断开时BLOCK函数也会返回的。没有影响吧。例子QNX文档里有:

/*
 *  This example opens a console and a serial port for
 *  read mode, and calls select() with a 5 second timeout.
 *  It waits for data to be available on either descriptor.
 */

#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/select.h>

int main( void )
{
    int console, serial;
    struct timeval tv;
    fd_set rfd;
    int n;

    if( ( console = open( "/dev/con1", O_RDONLY ) ) == -1
    ||    ( serial  = open( "/dev/ser1", O_RDONLY ) ) == -1 )
    {
      perror( "open" );
      return EXIT_FAILURE;
    }

    /*
     * Clear the set of read file descriptors, and
     * add the two we just got from the open calls.
     */
    FD_ZERO( &rfd );
    FD_SET( console, &rfd );
    FD_SET( serial,  &rfd );

    /*
     *    Set a 5 second timeout.
     */
    tv.tv_sec = 5;
    tv.tv_usec = 0;

for(;;)
{
    switch ( n = select( 1 + max( console, serial ),
           &rfd, 0, 0, &tv ) ) {
      case -1:
        perror( "select" );
        return EXIT_FAILURE;
      case  0:
        puts( "select timed out" );
        break;
      default:
        printf( "%d descriptors ready ...\n", n );
        if( FD_ISSET( console, &rfd ) )
          puts( " -- console descriptor has data pending" );
          //有数据,读,做相关操作,再返回select等待。
        if( FD_ISSET( serial, &rfd ) )
          puts( " -- serial descriptor has data pending" );
          //串口有数据,读......
    }
}
    return EXIT_SUCCESS;
}