NAME
getitimer, setitimer - get or set value of an interval timer
SYNOPSIS
#include <sys/time.h>
int getitimer(int which, struct itimerval *curr_value);
int setitimer(int which, const struct itimerval *new_value,
struct itimerval *old_value);
函数说明:
参数1 which
TIMER_REAL 以系统真实的时间来计算,时间到了 它送出SIGALRM信号。可以代替 alarm
ITIMER_VIRTUAL 以该进程在用户态下花费的时间来计算,它送出SIGVTALRM信号
ITIMER_PROF 以该进程在用户态下和内核态下所费的时间来计算。它送出SIGPROF信号。
相关结构体:
struct itimerval {
struct timeval it_interval; /* Interval for periodic timer */ 设置的定时器时间
struct timeval it_value; /* Time until next expiration */ 定时器剩余时间
};
struct timeval {
time_t tv_sec; /* seconds */
suseconds_t tv_usec; /* microseconds */
};
settimer工作机制是,先对it_value倒计时,当it_value为零时触发信号。然后重置为it_interval。继续对it_value倒计时。一直这样循环下去。
基于此机制。setitimer既能够用来延时运行,也可定时运行。
假如it_value为0是不会触发信号的,所以要能触发信号,it_value得大于0;假设it_interval为零,仅仅会延时。不会定时(也就是说仅仅会触发一次信号)。
参数2 new_value:
参数用来对计时器进行设置,it_interval为计时间隔,it_value为延时时长,如选择TIMER_REAL 时钟, 表示的是在setitimer方法调用成功后,延时it_value后触发一次SIGALRM信号,以后每隔it_interval触发一次SIGALRM信号。
参数3 old_value:通常用不上,设置为NULL,它是用来存储上一次setitimer调用时设置的new_value值。
On success, zero is returned. On error, -1 is returned, and errno is set appropriately
实验,流量控制之漏桶实验,用setitimer()实现
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <signal.h>
#include <sys/time.h>
#define BUFSIZE 10
static volatile int loop = 0;
static void alrm_handler(int s)
{
//alarm(1);
loop = 1;
}
int main(int argc,char *argv[])
{
int sfd,dfd=1;
char buf[BUFSIZE];
int len,ret,pos;
struct itimerval itv;
if(argc < 2)
{
fprintf(stderr,"Usage:%s <src_file> <dest_file>\n",argv[0]);
exit(1);
}
signal(SIGALRM,alrm_handler);
//alarm(1);
itv.it_interval.tv_sec = 1;
itv.it_interval.tv_usec = 0;
itv.it_value.tv_sec = 1;
itv.it_value.tv_usec = 1;
if(setitimer(ITIMER_REAL,&itv,NULL) < 0)
{
perror("setitimer()");
exit(1);
}
do
{
sfd = open(argv[1],O_RDONLY);
if(sfd < 0)
{
if(errno != EINTR)//signal
{
perror("open()");
exit(1);
}
}
}while(sfd < 0);
while(1)
{
while(!loop)
pause();
loop = 0;
while((len = read(sfd,buf,BUFSIZE)) < 0)
{ if(errno == EINTR)//signal
continue;
perror("read()");
break;
}
if(len == 0)
break;
//确保写进去 len 个字节
pos = 0;
while(len > 0)
{
ret = write(dfd,buf+pos,len);
if(ret < 0)
{
if(errno == EINTR) //signal
continue;
perror("write()");
exit(1);
}
pos += ret;
len -= ret;
}
}
close(sfd);
}