1.使用14号信号SIGALRM,调用alarm函数
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <signal.h> void handle(int signum) { printf("hello\n"); } int main(int argc, const char *argv[]) { signal(SIGALRM, handle); while(1) { alarm(3); sleep(3); } return 0; }
//每隔3秒向自身发送一个SIGALRM信号,signal收到 SIGALRM信号后调用handle进行处理
--》alarm只能精确到秒
2.setitimer -->也是通过向自身发送信号进行处理的,不过可以精确到毫妙级别
int setitimer(int which, const struct itimerval *new_value,
struct itimerval *old_value);
ITIMER_REAL decrements in real time, and delivers SIGALRM upon expiration.
ITIMER_VIRTUAL decrements only when the process is executing, and delivers
SIGVTALRM upon expiration.
ITIMER_PROF decrements both when the process executes and when the system is
executing on behalf of the process. Coupled with ITIMER_VIR-
TUAL, this timer is usually used to profile the time spent by
the application in user and kernel space. SIGPROF is delivered
upon expiration.
struct itimerval {
struct timeval it_interval; /* next value */
struct timeval it_value; /* current value */
};
struct timeval {
long tv_sec; /* seconds */
long tv_usec; /* microseconds */
};
--》3种模式产生3中不同的信号,使用方法类似
在该例子中,每隔一秒发出一个SIGALRM,每隔0.5秒发出一个SIGVTALRM信号: #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; } fflush(stdout); 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(;;) ; }
3.timerfd_create timerfd_settime -->通过时间设置fd可读,然后通过select轮询,调用处理函数
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/timerfd.h> #include <sys/time.h> #include <sys/types.h> #include <unistd.h> #include <errno.h> #define ERR_EXIT(m) do { perror(m); exit(EXIT_FAILURE); }while(0) int main(int argc, const char *argv[]) { struct itimerspec time; time.it_value.tv_sec = 5; time.it_interval.tv_sec = 2; int timerfd = timerfd_create(CLOCK_REALTIME, 0); if(timerfd == -1) ERR_EXIT("timerfd_create"); if(timerfd_settime(timerfd, 0, &time, NULL) == -1) ERR_EXIT("timerfd_settime"); fd_set read1, ready; FD_ZERO(&read1); FD_SET(timerfd, &read1); char buf[1024]; struct timeval time_select; while(1) { time_select.tv_sec = 3;//必须定义在while内部 time_select.tv_usec = 11; ready = read1; int nready = select(timerfd + 1, &ready, NULL, NULL, &time_select);//设置为一直阻塞 if(nready == -1) ERR_EXIT("select"); else if(nready == 0) printf("timeout"); else { if(-1 == read(timerfd, buf, sizeof buf)) { printf("%s\n", strerror(errno));//打印错误信息 ERR_EXIT("read"); } printf("come\n"); } } return 0; }
4.直接使用select -->精确到毫秒级别
int msSleep(long ms) { struct timeval tv; tv.tv_sec = 0; tv.tv_usec = ms; return select(0, NULL, NULL, NULL, &tv); }
其他资料:
http://www.cppblog.com/CppExplore/archive/2008/04/02/46111.html