Linux下的定时器有两种:
1、alarm
如果不要求很精确的话,用alarm()和signal()就够了。
unsigned int alarm(unsigned int seconds)
函数说明: alarm()用来设置信号SIGALRM在经过参数seconds指定的秒数后传送给目前的进程。如果参数seconds为0,则之前设置的闹钟会被取消,并将剩下的时间返回。
返回值: 返回之前闹钟的剩余秒数,如果之前未设闹钟则返回0.
alarm()执行后,进程将继续执行,在后期(alarm以后)的执行过程中将会在seconds秒后收到信号SIGALRM并执行其处理函数。
举例:
(1)
#include <stdio.h>#include <sys/time.h>#include <stdlib.h>#include <signal.h>#include <unistd.h>int count;void sigalrm_func(int sig){count++;printf("alarm![%d]\n",count);alarm(2);printf("over\n");return; }int main(void){signal(SIGALRM, sigalrm_func);alarm(3);printf("see\n");while(1);}
(2)
#include <stdio.h>#include <signal.h>#include <time.h>#include <unistd.h> //alarm()所在库int main(int argc, char *argv[]){sigset_t block;sigemptyset(&block);sigaddset(&block, SIGALRM);sigprocmask(SIG_BLOCK, &block, NULL);while (1) {printf("%ld\n", time(NULL));alarm(3);printf("see\n");sigwaitinfo(&block, NULL);}return 0;}
2、函数alarm设置的定时器只能精确到秒,而以下函数理论上可以精确到微妙:
#include <sys/time.h>int getitimer(int which, struct itimerval *value);int setitimer(int which, const struct itimerval *value, struct itimerval *ovalue);
setitimer()比alarm功能强大,支持3种类型的定时器(参数which):
第一个参数which指定定时器类型;
第二个参数是结构itimerval的一个实例;
第三个参数可不做处理。
setitimer()调用成功返回0,否则返回-1.
参数which确定了定时器的类型,如表1所示:
表1 参数which与定时器类型
结构itimerval描述了定时器的组成:
struct itimerval {struct tim it_interval;/* 下次定时取值 */struct tim it_value; /* 本次定时设置值 */}
结构tim描述了一个精确到微妙的时间:
struct tim{longtv_sec; /* 秒(1000000微秒) */longtv_usec;/* 微妙 */}
函数setitimer设置一个定时器,参数value指向一个itimerval结构,该结构决定了设置的定时器信息,结构成员it_value指定首次定时的时间,结构成员it_interval指定下次定时的时间。
定时器工作时,先将it_value的时间值减到0,发送一个信号,再将it_value赋值为it_interval的值,重新开始定时,如此反复。如果it_value值被设置为0,则定时器停止定时;如果it_value值不为0但it_interval值为0,则定时器在一次定时后终止。
函数setitimer调用成功时返回0,否则返回-1,参数ovalue如果不为空,返回上次的定时器状态。
函数getitimer获取当前的定时器状态,整型参数which指定了读取的定时器类型,参数value返回定时器状态。函数调用成功返回0,否则返回-1。
举例(1)
#include <stdio.h>#include <sys/time.h>#include <stdlib.h>#include <signal.h>int count = 0;void set_timer(){struct itimerval itv;itv.it_interval.tv_sec = 1;//每隔1秒itv.it_interval.tv_usec = 0;itv.it_value.tv_sec = 3;//第一次3秒itv.it_value.tv_usec = 0;setitimer(ITIMER_REAL, &itv, NULL);}void sigalrm_handler(int sig){count++;printf("timer signal.. %d\n", count);}int main(){signal(SIGALRM, sigalrm_handler);set_timer();while (count < 100){}exit(0);}
(2)
#include <stdio.h>#include <signal.h>#include <sys/time.h>#include <time.h>int main(int argc, char *argv[]){sigset_t block;struct itimerval itv;sigemptyset(&block);sigaddset(&block, SIGALRM);sigprocmask(SIG_BLOCK, &block, NULL);itv.it_interval.tv_sec = 5;itv.it_interval.tv_usec = 0;itv.it_value = itv.it_interval;setitimer(ITIMER_REAL, &itv, NULL);while (1) {printf("%ld\n", time(NULL));printf("see\n");sigwaitinfo(&block, NULL);}return 0;}
3、信号相关
#include <signal.h>int sigwaitinfo(sigset_t *set, siginfo_t *info)
sigwaitinfo()函数:阻塞一个进程直到特定信号发生,但信号到来时不执行信号处理函数,而是返回信号值。 调用该函数的典型代码为:
sigwaitinfo()sigset_t newmask;int rcvd_sig;siginfo_t info;sigemptyset(&newmask);sigaddset(&newmask, SIGRTMIN);sigprocmask(SIG_BLOCK, &newmask, NULL);rcvd_sig = sigwaitinfo(&newmask, &info);if(rcvd_sig == -1){…...}
1.信号集定义为一种数据类型,用来描述信号的集合:
typedef struct{unsigned long sig[_NSIG_WORDS];}sigset_t
2.int sigemptyset(sigset_t* set)
函数说明:用来将参数set信号集初始化并清空。
返回值:成功返回0,错误返回-1。
3.int sigaddset(sigset_t* set, int signum)
函数说明:用来将signum代表的信号加入至参数set信号集里。
返回值:成功返回0,错误返回-1。
4.int sigpromask(int how, const sigset_t* set, sigset_t* oldset)
函数说明:用来改变目前的信号遮罩,其操作依参数how来决定。
返回值:成功返回0,错误返回-1。
5.void (signal(int signum, void(handler)(int)))(int);
函数说明: signal()会依据参数signum指定的信号编号来设置该信号的处理函数,当指定的信号到达时就会跳转参数handler指定的函数执行。
返回值:返回先前的信号处理函数指针,如果有错误返回SIG_ERR(-1)
参考文章:
1.Linux下的定时器:/uid-317451-id-92667.html
2.linux的定时器(timer_create,timer_gettime,timer_delete,SIGEV_SIGNAL):
/uid-28458801-id-5035347.html
POSIX定时器:timer_settime()以及POSIX 线程见下一篇。