”如何使用setitimer来定时“ 这片文章讲解了如何使用timer来完成定时工作,但是它使用了一个休眠函数,对于信号的处理实时性不好,这里有了一套改进的方法,以供网友讨论。
#include <iostream>
#include <sys/time.h>
#include <signal.h>
#include <assert.h>
using namespace std;
class SignalUtil
{
void (*sigHandler)( int signum );
int signum;
struct sigaction oact;
void installSignal()
{
struct sigaction cact;
// Initialize current structure of signal action
sigemptyset( &cact.sa_mask );
cact.sa_flags = 0;
cact.sa_handler = sigHandler;
// Install signal hander
int res = sigaction( signum, &cact, &oact );
assert( res == 0 );
}
void uninstallSignal()
{
// Restore signal action
int res = sigaction( signum, &oact, NULL );
assert( res == 0 );
}
public:
SignalUtil( void (*_sigHandler)( int signum ), int _signum )
: sigHandler( _sigHandler ), signum( _signum )
{
cout << "SinUtil constructor" << endl;
installSignal();
}
virtual ~SignalUtil()
{
cout << "SinUtil destructor" << endl;
uninstallSignal();
}
// When receiving signal, it will return. Otherwise blocking it forever
virtual void waitSignal()
{
sigset_t cset;
sigset_t oset;
sigset_t wset;
// Initialize waiting signal set
int res = sigemptyset( &wset );
assert( res == 0 );
// Acquire current signal set
res = sigprocmask( 0, NULL, &cset );
assert( res == 0 );
// Mark flags to block signal
res = sigaddset( &cset, signum );
assert( res == 0 );
// Block signal
res = sigprocmask( SIG_BLOCK, &cset, &oset );
assert( res == 0 );
// Wait signal
res = sigsuspend( &wset );
assert( res == -1 && errno == EINTR );
// Restore signal
res = sigprocmask( SIG_BLOCK, &oset, NULL );
assert( res == 0 );
}
};
volatile static long counter = 0;
static void notify( int signum )
{
assert( signum == SIGALRM );
cout << "Notify" << endl;
++ counter;
}
static void installTimer( void )
{
struct itimerval tim_ticks;
tim_ticks.it_value.tv_sec = 0;
tim_ticks.it_value.tv_usec = 10;
tim_ticks.it_interval.tv_sec = 0;
tim_ticks.it_interval.tv_usec = 10;
int res = setitimer( ITIMER_REAL, &tim_ticks, 0 );
assert( res == 0 );
}
int main( void )
{
SignalUtil sigUtil( notify, SIGALRM );
installTimer();
for ( ; ; )
{
sigUtil.waitSignal();
cout << "counter = " << counter << endl;
}
return 0;
}
#include <iostream>
#include <sys/time.h>
#include <signal.h>
#include <assert.h>
using namespace std;
class SignalUtil
{
void (*sigHandler)( int signum );
int signum;
struct sigaction oact;
void installSignal()
{
struct sigaction cact;
// Initialize current structure of signal action
sigemptyset( &cact.sa_mask );
cact.sa_flags = 0;
cact.sa_handler = sigHandler;
// Install signal hander
int res = sigaction( signum, &cact, &oact );
assert( res == 0 );
}
void uninstallSignal()
{
// Restore signal action
int res = sigaction( signum, &oact, NULL );
assert( res == 0 );
}
public:
SignalUtil( void (*_sigHandler)( int signum ), int _signum )
: sigHandler( _sigHandler ), signum( _signum )
{
cout << "SinUtil constructor" << endl;
installSignal();
}
virtual ~SignalUtil()
{
cout << "SinUtil destructor" << endl;
uninstallSignal();
}
// When receiving signal, it will return. Otherwise blocking it forever
virtual void waitSignal()
{
sigset_t cset;
sigset_t oset;
sigset_t wset;
// Initialize waiting signal set
int res = sigemptyset( &wset );
assert( res == 0 );
// Acquire current signal set
res = sigprocmask( 0, NULL, &cset );
assert( res == 0 );
// Mark flags to block signal
res = sigaddset( &cset, signum );
assert( res == 0 );
// Block signal
res = sigprocmask( SIG_BLOCK, &cset, &oset );
assert( res == 0 );
// Wait signal
res = sigsuspend( &wset );
assert( res == -1 && errno == EINTR );
// Restore signal
res = sigprocmask( SIG_BLOCK, &oset, NULL );
assert( res == 0 );
}
};
volatile static long counter = 0;
static void notify( int signum )
{
assert( signum == SIGALRM );
cout << "Notify" << endl;
++ counter;
}
static void installTimer( void )
{
struct itimerval tim_ticks;
tim_ticks.it_value.tv_sec = 0;
tim_ticks.it_value.tv_usec = 10;
tim_ticks.it_interval.tv_sec = 0;
tim_ticks.it_interval.tv_usec = 10;
int res = setitimer( ITIMER_REAL, &tim_ticks, 0 );
assert( res == 0 );
}
int main( void )
{
SignalUtil sigUtil( notify, SIGALRM );
installTimer();
for ( ; ; )
{
sigUtil.waitSignal();
cout << "counter = " << counter << endl;
}
return 0;
}