基于 setitimer 实现的精确计时 sleep

2015-01-09 11:02:11   最后更新: 2015-01-09 11:16:35   访问数量:653




在 linux 下,使用 alarm 和 signal 或 sigsuspend 可以实现系统的 sleep 功能,可以参看:

sleep 函数的实现

但是如果使用 setittimer 与 sigsuspend 可以实现精度较高的定时功能

int setitimer(int which, const struct itimerval *value, struct itimerval *ovalue);

 

定义于 sys/time.h 中

调用成功返回 0 否则返回 -1

which

定时器类型参数

定时器类型选项
取值说明到时发送信号
ITIMER_REAL以系统真实时间计算SIGALRM
ITIMER_VIRTUAL以进程在用户态下花费的时间来计算SIGALRM
ITIMER_PROF以进程在用户态和内核态下所花费的时间来计算SIGPROF

value

value 是一个 itimerval 结构的类型

itimerval 结构如下:

struct itimerval { struct timeval it_interval; struct timeval it_value; };

 

it_interval 指定间隔时间,it_value 指定初始定时时间,如果只指定 it_value,则只实现一次定时,否则会在超时后用 it_value 初始化为 it_interval 实现重复定时

timeval 结构如下:

struct timeval { long tv_sec; long tv_usec; };

 

tv_sec 提供秒级精度,tv_usec 提供微秒级精度(1s = 1000000us)

ovalue

ovalue 参数也是一个 itimerval 结构类型参数,用来保存先前的值,通常设为 NULL

/* * file: main.c * author: 龙泉居士 * date: 2015-01-09 */ #include "function/function.h" int main () { unsigned int remain; printf ("ready for sleep\n"); remain = sleep_setitimer(1050); printf ("I have slept for 1050 ms and remain %d\n", remain); return 0; }

 

/* * file: function.h * author: 龙泉居士 * date: 2015-01-09 */ #ifndef _FUNCTION_H_20150109_ #define _FUNCTION_H_20150109_ #include <time.h> #include <stdio.h> #include <unistd.h> #include <signal.h> #include <stdlib.h> #include <string.h> #include <sys/time.h> unsigned int sleep_setitimer(unsigned int); #endif

 

/* * file: function.c * author: 龙泉居士 * date: 2015-01-09 */ #include "function.h" static void sig_alrm(int signo) { /* do nothing*/ } unsigned int sleep_setitimer(unsigned int msecs) { struct sigaction newact, oldact; sigset_t newmask, oldmask, suspmask; struct itimerval itv; struct itimerval otv; newact.sa_handler = sig_alrm; sigemptyset(&newact.sa_mask); newact.sa_flags = 0; sigaction(SIGALRM, &newact, &oldact); sigemptyset(&newmask); sigaddset(&newmask, SIGALRM); sigprocmask(SIG_BLOCK, &newmask, &oldmask); itv.it_interval.tv_sec = 0; itv.it_interval.tv_usec = 0; itv.it_value.tv_sec = msecs / 1000; itv.it_value.tv_usec = (msecs % 1000 ) * 1000; // 设定精确的定时功能,以系统时间计算 if (setitimer(ITIMER_REAL, &itv, NULL) == -1) { perror("setitimer"); exit(-1); } suspmask = oldmask; sigdelset(&suspmask, SIGALRM); sigsuspend(&suspmask); memset(&itv, 0, sizeof(struct itimerval)); if (setitimer(ITIMER_REAL, &itv, &otv) == -1) { perror("setitimer"); exit(-1); } sigaction(SIGALRM, &oldact, NULL); sigprocmask(SIG_SETMASK, &oldmask, NULL); return (otv.it_value.tv_sec*1000 + otv.it_value.tv_usec/1000); }

 

 






linux      unix      龙潭书斋      apue      unix环境高级编程      time      signal      sigprocmask      sigsuspend      sleep      setitimer      itimerval     


京ICP备15018585号