各位大侠,现在有个问题请教,我现在在编写一个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;
}