本文共 4328 字,大约阅读时间需要 14 分钟。
Linux下的定时器有两种:
1、alarm
如果不要求很精确的话,用alarm()和signal()就够了。
unsigned int alarm(unsigned int seconds)
函数说明: alarm()用来设置信号SIGALRM在经过参数seconds指定的秒数后传送给目前的进程。如果参数seconds为0,则之前设置的闹钟会被取消,并将剩下的时间返回。
返回值: 返回之前闹钟的剩余秒数,如果之前未设闹钟则返回0.
alarm()执行后,进程将继续执行,在后期(alarm以后)的执行过程中将会在seconds秒后收到信号SIGALRM并执行其处理函数。
举例:
(1)#include#include #include #include #include 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#include #include #include //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设置的定时器只能精确到秒,而以下函数理论上可以精确到微妙:
#includeint 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#include #include #include 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#include #include #include 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、信号相关
#includeint 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下的定时器: 2.linux的定时器(timer_create,timer_gettime,timer_delete,SIGEV_SIGNAL):POSIX定时器:timer_settime()以及POSIX 线程见下一篇。