zoukankan      html  css  js  c++  java
  • 应用层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
    ", (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
    ", (long) *tidp);
    
        or = timer_getoverrun(*tidp);
        if(or == -1){
            errExit("timer_getoverrun");
        } else {
            printf(" overrun count = %d
    ", 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
    ", 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>
    ", argv[0]);
            exit(EXIT_FAILURE);
        }
    
        printf("Establishing handler for signal %d
    ", 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
    ", 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
    ", (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
    ", atoi(argv[1]));
        sleep(atoi(argv[1]));
    
        printf("Unblocking signal %d
    ", 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]
    ", pthread_self(), (char *)sv.sival_ptr);
    //    printf("thread run: %lu...[%d]
    ", 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.
    ");
            return (timer_t)-1;
        }else {
            printf("create timer id: %lx
    ", (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.
    ");
            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.
    ");
            return -1;
        }
        ret = pthread_detach(thid);
        if(ret < 0){
            printf("pthread_detach failed.
    ");
            return -1;
        }
    */
        tid = timer_add(2, 0, timer_thread, (void *)str);
        if(tid < 0){
            printf("timer add failed.
    ");
            return -1;
        }
    
        while(1);
    //    sleep(5);
        
        timer_delete(tid);
        return 0;    
    }

    参考:

    1. Linux 下定时器的实现方式分析

  • 相关阅读:
    Java对【JSON数据的解析】--Gson解析法
    Java对【JSON数据的解析】--官方解析法
    Java之JSON数据
    网络编程应用:基于UDP协议【实现聊天程序】--练习
    {网络编程}和{多线程}应用:基于UDP协议【实现多发送方发送数据到同一个接收者】--练习
    PHP获取页面执行时间的方法(推荐)
    Linux下查看CPU型号,内存大小,硬盘空间的命令(详解)
    Elasticsearch 全字段搜索_all,query_string查询,不进行分词
    mysql 查询某字段值全是数字
    linux服务器中Apache隐藏index.php失败
  • 原文地址:https://www.cnblogs.com/embedded-linux/p/9093924.html
Copyright © 2011-2022 走看看