• 闹钟设计


    问题:如果只有一个定时器,如何设置多个闹钟,并不使用全局变量、环境变量等传参

    解决:拓展定时器信号的处理函数接口,封装一个结构体,存放定时时间sec,定时模式:mod,计时变量count,超时行为func(),行为函数的参数arg,  为了方便后面删除一个闹钟节点,所以需要一个唯一标示,故用每个节点的地址作为Id,   为了方便查找和删除所以设计成一个双向循环链表。

    流程:main函数添加闹钟节点到链表中,定时器设置为每隔1s触发一次超时信号,在信号处理函数内对信号链表进行遍历,查看此时count 与sec是否相等,如果相等则执行超时行为,接着判断mode,如果为loop,则将count重新置0,若为ONCE则删除该节点。   最后再次将闹钟激活alarm(1).

    代码示例:

    #include <stdio.h>
    #include <stdlib.h>
    #include <signal.h>
    #include <unistd.h>

    #define       LOOP       0x0001
    #define       ONCE       0x0002
    #define       TIME_ERR   -1

    typedef  long   TIME_ID;

    typedef struct node{
        int   sec;   //定时值
        int   count; //计数器
        int   mode;  //LOOP/ONCE
        void  (*func)(void *);//超时行为
        void  *arg;  //func调用参数

        TIME_ID  id;

        struct node  *prev,*next;
    }Timer_t;
    static   Timer_t  *head;
    ////////////////////////////////////////////////////////
    void sigFunc(int signo);
    int  initTimer(void);
    TIME_ID  addTimer(int sec,int mode,void (*func)(void *),void *arg);
    void deleteTimer(TIME_ID  id);
    void destoryTimer(void);

    /////////////////////////////////////////////////////////
    void sayHello(void *arg);
    void show(void *arg);
    void printVal(void *arg);


    int main(void)
    {
        int ret;
        int val=5566;

        ret=initTimer();
        if(ret!=0)
        {
            fprintf(stderr,"init timer failed. ");
            return 1;
        }
        //
        TIME_ID  ids[3];
        ids[0]=addTimer(3,LOOP,sayHello,"king");
        if(ids[0]==TIME_ERR)
        {
            fprintf(stderr,"add sayhello timer failed ");
        }
        ids[1]=addTimer(5,ONCE,show,NULL);
        //if error
        ids[2]=addTimer(10,LOOP,printVal,&val);
        //if error

        printf("33[31mEnter Del SayHello Timer33[0m ");
        getchar();
        deleteTimer(ids[0]);


        
        getchar();
        destoryTimer();
        return 0;
    }
    int  initTimer(void)
    {

        head=malloc(sizeof(Timer_t));
        if(head==NULL)   return -2;

        head->next=head;
        head->prev=head;

        if(signal(SIGALRM,sigFunc)==SIG_ERR)
           return -1;

         alarm(1);//启动系统定时器
         return 0;
    }
    /*
     *定时检查任务节点是否有超时的
    */
    void sigFunc(int signo)
    {
         Timer_t  *t,*next;
         
         for(t=head->next;t!=head;t=next)
         {
             next=t->next;
             //
             t->count=t->count+1;//计时
             if(t->count==t->sec)//超时 执行行为
             {
                 t->func(t->arg);
                 //检查类型
                 if(t->mode==LOOP)
                 {
                      t->count=0;
                 }
                 else
                 {
                      t->next->prev=t->prev;
                      t->prev->next=t->next;
                      free(t);
                 }
             }
         }
         alarm(1);
    }
    //追加任务节点
    TIME_ID addTimer(int sec,int mode,void (*func)(void *),void *arg)
    {
         Timer_t  *one;
         one=malloc(sizeof(Timer_t));
         if(one==NULL)   return TIME_ERR;

         one->sec  =sec;
         one->count=0;
         one->mode =mode;
         one->func =func;
         one->arg  =arg;
         one->id   =(TIME_ID)one;

         //
         one->next=head;
         one->prev=head->prev;
         one->next->prev=one;
         one->prev->next=one;
         return one->id;
    }

    void deleteTimer(TIME_ID  id)
    {
         Timer_t  *t,*next;
         for(t=head->next;t!=head;t=next)
         {
             next=t->next;
             if(t->id==id)
             {
                t->next->prev=t->prev;
                t->prev->next=t->next;
                free(t);
             }
         }

    }
    void destoryTimer(void)
    {
         Timer_t  *t,*next;
         alarm(0);
         for(t=head->next;t!=head;t=next)
         {
             next=t->next;
             free(t);
         }
         free(head);
         signal(SIGALRM,SIG_DFL);
    }



    /////////////////////////////////////////////////////
    void sayHello(void *arg)
    {
          printf("Hello %s ",(char *)arg);
    }
    void show(void *arg)
    {
          printf("============show======== ");
    }
    void printVal(void *arg)
    {
          printf("<<<<<val:%d>>>>>> ",*(int *)arg);
    }

  • 相关阅读:
    spring boot——集成mongodb——mongodb安装
    spring boot——集成JPA——入门示例001
    spring boot——集成swagger——入门示例
    spring boot——集成redis——序列化——stringRedisTemplate与redisTemplate=========JdkSerializationRedisSerializer与StringRedisSerializer了解
    spring boot——集成redis——示例参考——stringRedisTemplate与redisTemplate
    PhpSpreadsheet导出科学记数转成字符串
    测试大纲
    毕业设计进度对照表
    TS ES6 VUE 相关
    类加载器隔离朴实案例(三)logback实战加密
  • 原文地址:https://www.cnblogs.com/edan/p/8946778.html
Copyright © 2020-2023  润新知