zoukankan      html  css  js  c++  java
  • timer_create and timer_settime

    http://man7.org/linux/man-pages/man2/timer_create.2.html

    http://man7.org/linux/man-pages/man7/sigevent.7.html

    http://man7.org/linux/man-pages/man2/timer_settime.2.html

    #include <signal.h>
    #include <time.h>

    int timer_create(clockid_t clockid, struct sigevent *sevp, timer_t *timerid);

           struct sigevent {
               int          sigev_notify; /* Notification method */
               int          sigev_signo;  /* Notification signal */
               union sigval sigev_value;  /* Data passed with
                                             notification */
               void       (*sigev_notify_function) (union sigval);
                                /* Function used for thread
                                   notification (SIGEV_THREAD) */
               void        *sigev_notify_attributes;
                                /* Attributes for notification thread
                                   (SIGEV_THREAD) */
               pid_t        sigev_notify_thread_id;
                                /* ID of thread to signal (SIGEV_THREAD_ID) */
           };

    SIGEV_NONE
    Don't asynchronously notify when the timer expires. Progress of the timer can be monitored using timer_gettime(2).

    SIGEV_SIGNAL
    Upon timer expiration, generate the signal sigev_signo for the process. See sigevent(7) for general details. The si_code field of the siginfo_t structure will be set to SI_TIMER. At any point in time, at most one signal is queued to the process
    for a given timer; see timer_getoverrun(2) for more details.

    SIGEV_THREAD
    Upon timer expiration, invoke sigev_notify_function as if it were the start function of a new thread. See sigevent(7) for details.

    SIGEV_THREAD_ID (Linux-specific)
    As for SIGEV_SIGNAL, but the signal is targeted at the thread whose ID is given in sigev_notify_thread_id, which must be a thread in the same process as the caller. The sigev_notify_thread_id field specifies a kernel thread ID, that is, the value returned by clone(2) or gettid(2). This flag is intended only for use by threading libraries.

    #include <time.h>

    int timer_settime(timer_t timerid, int flags,const struct itimerspec *new_value,struct itimerspec *old_value);
    int timer_gettime(timer_t timerid, struct itimerspec *curr_value);

    struct itimerspec {
                   struct timespec it_interval;  /* Timer interval */
                   struct timespec it_value;     /* Initial expiration */
               };

    If new_value->it_value specifies a nonzero value (i.e., either sub‐field is nonzero), then timer_settime() arms (starts) the timer, set‐ting it to initially expire at the given time. (If the timer was already armed, then the previous settings are overwritten.) If
    new_value->it_value specifies a zero value (i.e., both subfields are zero), then the timer is disarmed.

    The new_value->it_interval field specifies the period of the timer, in seconds and nanoseconds. If this field is nonzero, then each time that an armed timer expires, the timer is reloaded from the value specified in new_value->it_interval. If new_value->it_interval spec‐ifies a zero value, then the timer expires just once, at the time specified by it_value.

    1,信号量方式

           #include <stdlib.h>
           #include <unistd.h>
           #include <stdio.h>
           #include <signal.h>
           #include <time.h>
    
           #define CLOCKID CLOCK_REALTIME
           #define SIG SIGRTMIN
    
           #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("    sival_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 safe
                  (and should not be done in production programs), since
                  printf() is not async-signal-safe; see signal-safety(7).
                  Nevertheless, we use printf() here as a simple way of
                  showing that the handler was called. */
    
               printf("Caught signal %d
    ", sig);
               print_siginfo(si);
               signal(sig, SIG_IGN);
           }
    
           int
           main(int argc, char *argv[])
           {
               timer_t timerid;
               struct sigevent sev;
               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);
               }
    
               /* Establish handler for timer signal */
               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");
    
               /* Block timer signal temporarily */
               printf("Blocking signal %d
    ", SIG);
               sigemptyset(&mask);
               sigaddset(&mask, SIG);
               if (sigprocmask(SIG_SETMASK, &mask, NULL) == -1)
                   errExit("sigprocmask");
    
               /* Create the timer */
               sev.sigev_notify = SIGEV_SIGNAL;
               sev.sigev_signo = SIG;
               sev.sigev_value.sival_ptr = &timerid;
               if (timer_create(CLOCKID, &sev, &timerid) == -1)
                   errExit("timer_create");
    
               printf("timer ID is 0x%lx
    ", (long) timerid);
    
               /* 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 = its.it_value.tv_sec;
               its.it_interval.tv_nsec = its.it_value.tv_nsec;
               if (timer_settime(timerid, 0, &its, NULL) == -1)
                    errExit("timer_settime");
    
               /* Sleep for a while; meanwhile, the timer may expire
                  multiple times */
               printf("Sleeping for %d seconds
    ", atoi(argv[1]));
               sleep(atoi(argv[1]));
    
               /* Unlock the timer signal, so that timer notification
                  can be delivered */
    
               printf("Unblocking signal %d
    ", SIG);
               if (sigprocmask(SIG_UNBLOCK, &mask, NULL) == -1)
                   errExit("sigprocmask");
    
               exit(EXIT_SUCCESS);
           }

    2,线程方式

    #include <stdio.h>
    #include <signal.h>
    #include <time.h>
    #include <string.h>
    #include <stdlib.h>
    #include <unistd.h>
    
    #define CLOCKID CLOCK_REALTIME
    
    void timer_thread(union sigval v)
    {
        printf("timer_thread function! %d
    ", v.sival_int);
    }
    
    int main()
    {
        // XXX int timer_create(clockid_t clockid, struct sigevent *evp, timer_t *timerid);
        // clockid--值:CLOCK_REALTIME,CLOCK_MONOTONIC,CLOCK_PROCESS_CPUTIME_ID,CLOCK_THREAD_CPUTIME_ID
        // evp--存放环境值的地址,结构成员说明了定时器到期的通知方式和处理方式等
        // timerid--定时器标识符
        timer_t timerid;
        struct sigevent evp;
        memset(&evp, 0, sizeof(struct sigevent));    //清零初始化
    
        evp.sigev_value.sival_int = 111;        //也是标识定时器的,这和timerid有什么区别?回调函数可以获得
        evp.sigev_notify = SIGEV_THREAD;        //线程通知的方式,派驻新线程
        evp.sigev_notify_function = timer_thread;    //线程函数地址
        if (timer_create(CLOCKID, &evp, &timerid) == -1)
        {
            perror("fail to timer_create");
            exit(-1);
        }
    
        // XXX int timer_settime(timer_t timerid, int flags, const struct itimerspec *new_value,struct itimerspec *old_value);
        // timerid--定时器标识
        // flags--0表示相对时间,1表示绝对时间,通常使用相对时间
        // new_value--定时器的新初始值和间隔,如下面的it
        // old_value--取值通常为0,即第四个参数常为NULL,若不为NULL,则返回定时器的前一个值
        
        //第一次间隔it.it_value这么长,以后每次都是it.it_interval这么长,就是说it.it_value变0的时候会装载it.it_interval的值
        //it.it_interval可以理解为周期
        struct itimerspec it;
        it.it_interval.tv_sec = 1;    //间隔1s
        it.it_interval.tv_nsec = 0;
        it.it_value.tv_sec = 1;        
        it.it_value.tv_nsec = 0;
        if (timer_settime(timerid, 0, &it, NULL) == -1)
        {
            perror("fail to timer_settime");
            exit(-1);
        }
    
        pause();
    
        return 0;
    }
    
  • 相关阅读:
    【php学习之路】微信公众帐号
    【php学习之路】php基础语法
    WCF全局异常处理
    【原创】【2015最新】微信公众平台开发手把手入门之一:缘起微信公众号(PHP,MYSQL, BAE)
    【原创】【2015最新】微信公众平台开发手把手入门之四:SVN和验证消息真实性(PHP,MYSQL, BAE)
    【原创】【2015最新】微信公众平台开发手把手入门之三:申请百度开放平台BAE云服务(PHP,MYSQL, BAE)
    【原创】【2015最新】微信公众平台开发手把手入门之二:开发者模式(PHP,MYSQL, BAE)
    微信公众号PHP简单开发流程
    angular+requirejs前端整合
    04、AngularJS的ng-bind、多个控制器和apply
  • 原文地址:https://www.cnblogs.com/soul-stone/p/8655832.html
Copyright © 2011-2022 走看看