应用层timer_libc_posix timer
应用层除了通过setitimer/getitimer设置获取timer外,还可通过timer_create()等一系列函数实现应用层timer功能。
应用流程
The timers created by timer_create() are commonly known as "POSIX (interval) timers". The POSIX timers API consists of the following interfaces:
* timer_create(): Create a timer.
* timer_settime(2): Arm (start) or disarm (stop) a timer.
* timer_gettime(2): Fetch the time remaining until the next expiration of a timer, along with the interval setting of the timer.
* timer_getoverrun(2): Return the overrun count for the last timer expiration.
* timer_delete(2): Disarm and delete a timer.
timer_create
#include <signal.h> #include <time.h> int timer_create(clockid_t clockid, struct sigevent *sevp, timer_t *timerid);
timer_create() creates a new per-process interval timer. The ID of the new timer is returned in the buffer pointed to by timerid, which must be a non-null pointer.
参数clockid
CLOCK_REALTIME A settable system-wide real-time clock. 一般此id。
CLOCK_MONOTONIC
A nonsettable monotonically increasing clock that measures time from some unspecified point in the past that does not change after system startup.
CLOCK_PROCESS_CPUTIME_ID (since Linux 2.6.12)
A clock that measures (user and system) CPU time consumed by (all of the threads in) the calling process.
CLOCK_THREAD_CPUTIME_ID (since Linux 2.6.12)
A clock that measures (user and system) CPU time consumed by the calling thread.
参数sigevent
指定超时的动作,详见man sigevent。
The sevp.sigev_notify field can have the following values:SIGEV_NONE(不处理),SIGEV_SIGNAL(产生信号),SIGEV_THREAD(新线程处理),SIGEV_THREAD_ID(指定线程处理)。
参数timerid
typedef void * timer_t; timer_t timerid; printf("timer ID is 0x%lx\n", (long)timerid);
返回值
成功返回0,timerid保存创建的timer。
manpage示例--SIGEV_SIGNAL:
#include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <string.h> #include <time.h> #include <signal.h> #define SIG SIGTERM #define errExit(msg) \ do {perror(msg); exit(EXIT_FAILURE); } while(0) static void print_siginfo(siginfo_t *si) { timer_t *tidp; int or; tidp = si->si_value.sival_ptr; printf("sigval_ptr = %p; ", si->si_value.sival_ptr); printf(" *sival_ptr =0x%lx\n", (long) *tidp); or = timer_getoverrun(*tidp); if(or == -1){ errExit("timer_getoverrun"); } else { printf(" overrun count = %d\n", or); } } static void handler(int sig, siginfo_t *si, void *uc) { /* Note: calling printf() from a signal handler is not strictly correct, since printf() is not async-signal-safe; see signal(7) */ printf("Caught signal %d\n", sig); print_siginfo(si); signal(sig, SIG_IGN); } int main(int argc, char **argv) { int ret = 0; timer_t timerid; struct sigevent se; struct itimerspec its; long long freq_nanosecs; sigset_t mask; struct sigaction sa; if(argc != 3){ fprintf(stderr, "Usage:%s <sleep-secs> <freq_nanosecs>\n", argv[0]); exit(EXIT_FAILURE); } printf("Establishing handler for signal %d\n", SIG); sa.sa_flags = SA_SIGINFO; sa.sa_sigaction = handler; sigemptyset(&sa.sa_mask); if(sigaction(SIG, &sa, NULL) == -1){ errExit("sigaction"); } printf("Blocking signal %d\n", SIG); sigemptyset(&mask); sigaddset(&mask, SIG); if(sigprocmask(SIG_SETMASK, &mask, NULL) == -1){ errExit("sigprocmask"); } memset(&se, 0, sizeof(struct sigevent)); se.sigev_notify = SIGEV_SIGNAL; se.sigev_signo = SIG; se.sigev_value.sival_ptr = &timerid; ret = timer_create(CLOCK_REALTIME, &se, &timerid); if(!ret){ printf("timer create successfully, timeid is 0x%lx\n", (long)timerid); } else { perror("timer_create"); } /* Start the timer */ freq_nanosecs = atoll(argv[2]); its.it_value.tv_sec = freq_nanosecs /1000000000; its.it_value.tv_nsec = freq_nanosecs %1000000000; its.it_interval.tv_sec = freq_nanosecs /1000000000; its.it_interval.tv_nsec = freq_nanosecs %1000000000; if(timer_settime(timerid, 0, &its, NULL) == -1){ errExit("timer_settime"); } printf("Sleeping for %d secs\n", atoi(argv[1])); sleep(atoi(argv[1])); printf("Unblocking signal %d\n", SIG); if(sigprocmask(SIG_UNBLOCK, &mask, NULL) == -1){ errExit("sigprocmask"); } exit(EXIT_SUCCESS); }
SIGEV_THREAD示例:
#include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <string.h> #include <pthread.h> #include <signal.h> #include <time.h> //void * timer_thread(void *arg) void timer_thread(union sigval sv) { printf("thread run: %lu...[%s]\n", pthread_self(), (char *)sv.sival_ptr); // printf("thread run: %lu...[%d]\n", pthread_self(), (char *)sv.sival_int); // return NULL; } timer_t timer_add(long sec, long usec, void (*func)(union sigval), void *arg) { int ret = 0; timer_t tid; struct sigevent sev; memset(&sev, 0, sizeof(sev)); sev.sigev_notify = SIGEV_THREAD; sev.sigev_notify_function = func; sev.sigev_value.sival_ptr = arg; ret = timer_create(CLOCK_MONOTONIC, &sev, &tid); if(ret < 0){ printf("timer_create failed.\n"); return (timer_t)-1; }else { printf("create timer id: %lx\n", (long)tid); } struct itimerspec its; memset(&its, 0, sizeof(its)); its.it_interval.tv_sec = sec; its.it_interval.tv_nsec = usec * 1000; its.it_value.tv_sec = 0; its.it_value.tv_nsec = 1; ret = timer_settime(tid, 0, &its, NULL); if(ret < 0){ printf("timer_settime failed.\n"); return (timer_t)-1; } return tid; } int main(int argc, char *argv[]) { timer_t tid; char str[] ="I love CHINA"; /* int ret = 0; pthread_t thid = 0; ret = pthread_create(&thid, NULL, timer_thread, NULL); if(ret < 0){ printf("create thread failed.\n"); return -1; } ret = pthread_detach(thid); if(ret < 0){ printf("pthread_detach failed.\n"); return -1; } */ tid = timer_add(2, 0, timer_thread, (void *)str); if(tid < 0){ printf("timer add failed.\n"); return -1; } while(1); // sleep(5); timer_delete(tid); return 0; }
参考: