应用层除了通过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() 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 == -){
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 = ;
timer_t timerid;
struct sigevent se;
struct itimerspec its;
long long freq_nanosecs;
sigset_t mask;
struct sigaction sa; if(argc != ){
fprintf(stderr, "Usage:%s <sleep-secs> <freq_nanosecs>\n", argv[]);
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) == -){
errExit("sigaction");
} printf("Blocking signal %d\n", SIG);
sigemptyset(&mask);
sigaddset(&mask, SIG);
if(sigprocmask(SIG_SETMASK, &mask, NULL) == -){
errExit("sigprocmask");
} memset(&se, , 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[]);
its.it_value.tv_sec = freq_nanosecs /;
its.it_value.tv_nsec = freq_nanosecs %;
its.it_interval.tv_sec = freq_nanosecs /;
its.it_interval.tv_nsec = freq_nanosecs %; if(timer_settime(timerid, , &its, NULL) == -){
errExit("timer_settime");
}
printf("Sleeping for %d secs\n", atoi(argv[]));
sleep(atoi(argv[])); printf("Unblocking signal %d\n", SIG);
if(sigprocmask(SIG_UNBLOCK, &mask, NULL) == -){
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 = ;
timer_t tid;
struct sigevent sev; memset(&sev, , 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 < ){
printf("timer_create failed.\n");
return (timer_t)-;
}else {
printf("create timer id: %lx\n", (long)tid);
} struct itimerspec its; memset(&its, , sizeof(its));
its.it_interval.tv_sec = sec;
its.it_interval.tv_nsec = usec * ;
its.it_value.tv_sec = ;
its.it_value.tv_nsec = ; ret = timer_settime(tid, , &its, NULL);
if(ret < ){
printf("timer_settime failed.\n");
return (timer_t)-;
} 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(, , timer_thread, (void *)str);
if(tid < ){
printf("timer add failed.\n");
return -;
} while();
// sleep(5); timer_delete(tid);
return ;
}
参考: