关于linux下的定时函数的一些认识解决思路
关于linux下的定时函数的一些认识
今天看书看到了关于alarm的一些用法,自己有在网上找了些资料看了下;
1。alarm()执行后,进程将继续执行,在后期(alarm以后)的执行过程中将会在seconds秒后收到信号SIGALRM并执行其处理函数。
2.alarm定时器,但是只能精确到秒,然而我们如果需要用到更精准的怎么办?
经过群里的大牛知道,看了下可以用setitimer
int setitimer(int which, const struct itimerval *value, struct itimerval *ovalue));
setitimer()比alarm功能强大,支持3种类型的定时器:
ITIMER_REAL : 以系统真实的时间来计算,它送出SIGALRM信号。
ITIMER_VIRTUAL : -以该进程在用户态下花费的时间来计算,它送出SIGVTALRM信号。
ITIMER_PROF : 以该进程在用户态下和内核态下所费的时间来计算,它送出SIGPROF信号。
setitimer()第一个参数which指定定时器类型(上面三种之一);第二个参数是结构itimerval的一个实例;第三个参数可不做处理。
setitimer()调用成功返回0,否则返回-1。
下面是关于setitimer调用的一个简单示范,在该例子中,每隔一秒发出一个SIGALRM,每隔0.5秒发出一个SIGVTALRM信号:
setitimer不会引起线程的阻塞、也不会引起线程的切换动作,就是简单的启动一个定时器,开始定时,而且这种定时应该是基于内核的,(windwos的settimer是基于一种消息的模型);setitimer虽然有三种类型ITIMER_REAL,ITIMER_VIRTUAL ITIMER_PROF,但是在同一时间同一进程,一种类型的只能有1个setitimer;
如果我们需要多个定时器怎么办?
3.
Linux下的微秒级定时器: usleep, nanosleep, select, pselect
今天看书看到了关于alarm的一些用法,自己有在网上找了些资料看了下;
1。alarm()执行后,进程将继续执行,在后期(alarm以后)的执行过程中将会在seconds秒后收到信号SIGALRM并执行其处理函数。
- C/C++ code
#include <stdio.h> #include <unistd.h> #include <signal.h> void sigalrm_fn(int sig) { printf("alarm!\n"); alarm(2); return; } int main(void) { signal(SIGALRM, sigalrm_fn); alarm(1); while(1) pause(); }
2.alarm定时器,但是只能精确到秒,然而我们如果需要用到更精准的怎么办?
经过群里的大牛知道,看了下可以用setitimer
int setitimer(int which, const struct itimerval *value, struct itimerval *ovalue));
setitimer()比alarm功能强大,支持3种类型的定时器:
ITIMER_REAL : 以系统真实的时间来计算,它送出SIGALRM信号。
ITIMER_VIRTUAL : -以该进程在用户态下花费的时间来计算,它送出SIGVTALRM信号。
ITIMER_PROF : 以该进程在用户态下和内核态下所费的时间来计算,它送出SIGPROF信号。
setitimer()第一个参数which指定定时器类型(上面三种之一);第二个参数是结构itimerval的一个实例;第三个参数可不做处理。
setitimer()调用成功返回0,否则返回-1。
下面是关于setitimer调用的一个简单示范,在该例子中,每隔一秒发出一个SIGALRM,每隔0.5秒发出一个SIGVTALRM信号:
- C/C++ code
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <signal.h> #include <time.h> #include <sys/time.h> int sec; void sigroutine(int signo){ switch (signo){ case SIGALRM: printf("Catch a signal -- SIGALRM \n"); signal(SIGALRM, sigroutine); break; case SIGVTALRM: printf("Catch a signal -- SIGVTALRM \n"); signal(SIGVTALRM, sigroutine); break; } return; } int main() { struct itimerval value, ovalue, value2; //(1) sec = 5; printf("process id is %d\n", getpid()); signal(SIGALRM, sigroutine); signal(SIGVTALRM, sigroutine); value.it_value.tv_sec = 1; value.it_value.tv_usec = 0; value.it_interval.tv_sec = 1; value.it_interval.tv_usec = 0; setitimer(ITIMER_REAL, &value, &ovalue); //(2) value2.it_value.tv_sec = 0; value2.it_value.tv_usec = 500000; value2.it_interval.tv_sec = 0; value2.it_interval.tv_usec = 500000; setitimer(ITIMER_VIRTUAL, &value2, &ovalue); for(;;) ; }
setitimer不会引起线程的阻塞、也不会引起线程的切换动作,就是简单的启动一个定时器,开始定时,而且这种定时应该是基于内核的,(windwos的settimer是基于一种消息的模型);setitimer虽然有三种类型ITIMER_REAL,ITIMER_VIRTUAL ITIMER_PROF,但是在同一时间同一进程,一种类型的只能有1个setitimer;
如果我们需要多个定时器怎么办?
3.
Linux下的微秒级定时器: usleep, nanosleep, select, pselect
- C/C++ code
#include<stdio.h> #include<stdlib.h> #include<time.h> #include<sys/time.h> #include<errno.h> #include<string.h> #include<unistd.h> #include<sys/types.h> #include<sys/select.h> int main(int argc, char **argv) { unsigned int nTimeTestSec = 0; unsigned int nTimeTest = 0; struct timeval tvBegin; struct timeval tvNow; int ret = 0; unsigned int nDelay = 0; struct timeval tv; int fd = 1; int i = 0; struct timespec req; unsigned int delay[20] = {500000, 100000, 50000, 10000, 1000, 900, 500, 100, 10, 1, 0}; int nReduce = 0; //误差 fprintf(stderr, "%19s%12s%12s%12s\n", "fuction", "time(usec)", "realtime", "reduce"); fprintf(stderr, "----------------------------------------------------\n"); for (i = 0; i < 20; i++) { if (delay[i] <= 0) break; nDelay = delay[i]; //test sleep gettimeofday(&tvBegin, NULL); ret = usleep(nDelay); if(ret == -1) { fprintf(stderr, "usleep error, errno=%d [%s]\n", errno, strerror(errno)); } gettimeofday(&tvNow, NULL); nTimeTest = (tvNow.tv_sec - tvBegin.tv_sec) * 1000000 + tvNow.tv_usec - tvBegin.tv_usec; nReduce = nTimeTest - nDelay; fprintf (stderr, "\t usleep %8u %8u %8d\n", nDelay, nTimeTest,nReduce); //test nanosleep req.tv_sec = nDelay/1000000; req.tv_nsec = (nDelay%1000000) * 1000; gettimeofday(&tvBegin, NULL); ret = nanosleep(&req, NULL); if (-1 == ret) { fprintf (stderr, "\t nanousleep %8u not support\n", nDelay); } gettimeofday(&tvNow, NULL); nTimeTest = (tvNow.tv_sec - tvBegin.tv_sec) * 1000000 + tvNow.tv_usec - tvBegin.tv_usec; nReduce = nTimeTest - nDelay; fprintf (stderr, "\t nanosleep %8u %8u %8d\n", nDelay, nTimeTest,nReduce); //test select tv.tv_sec = 0; tv.tv_usec = nDelay; gettimeofday(&tvBegin, NULL); ret = select(0, NULL, NULL, NULL, &tv); if (-1 == ret) { fprintf(stderr, "select error. errno = %d [%s]\n", errno, strerror(errno)); } gettimeofday(&tvNow, NULL); nTimeTest = (tvNow.tv_sec - tvBegin.tv_sec) * 1000000 + tvNow.tv_usec - tvBegin.tv_usec; nReduce = nTimeTest - nDelay; fprintf (stderr, "\t select %8u %8u %8d\n", nDelay, nTimeTest,nReduce); //pselcet req.tv_sec = nDelay/1000000; req.tv_nsec = (nDelay%1000000) * 1000; gettimeofday(&tvBegin, NULL); ret = pselect(0, NULL, NULL, NULL, &req, NULL); if (-1 == ret) { fprintf(stderr, "select error. errno = %d [%s]\n", errno, strerror(errno)); } gettimeofday(&tvNow, NULL); nTimeTest = (tvNow.tv_sec - tvBegin.tv_sec) * 1000000 + tvNow.tv_usec - tvBegin.tv_usec; nReduce = nTimeTest - nDelay; fprintf (stderr, "\t pselect %8u %8u %8d\n", nDelay, nTimeTest,nReduce); fprintf (stderr, "--------------------------------\n"); } return 0; }