您的位置:新葡亰496net > 电脑系统 > Linux计时系统布局,LINUX使用贰个放大计时器达成

Linux计时系统布局,LINUX使用贰个放大计时器达成

发布时间:2019-11-10 07:17编辑:电脑系统浏览(154)

    本例子仿效 Don Libes的Title: Implementing Software Timers例子改写

    LINUX使用三个放大计时器完结设置任性数量反应计时器,linux数量计时器

    本例子参照他事他说加以侦察 Don Libes的Title: Implementing Software Timers例子改写

     

     

    为啥要求那些意义,因为比较多应用软件石英钟系统平日只好有三个时钟触发一次中断。当运维几个职分时,大家会想要三个测量时间的装置的原子钟追踪并发那样能够转移不易的时间重叠,操作系统那样做。

     

    本例子是为着贯彻应用Linux下的三个反应计时器,完结任生机勃勃数量的电磁打点计时器功效。

    第生龙活虎我们必要一些数据类型用来说述石英钟数据结构

    #include <stdio.h>
    
    #include<time.h>
    
    #define TRUE 1
    #define FALSE    0
    
    #define MAX_TIMERS    ...    最大时钟数量
    typedef timerval TIME; 定义时间类型
    #define VERY_LONG_TIME    ... 最大时间长度
    
    struct timer {
    int inuse;    时钟是否可用
    TIME time; 定时时间长度
    char *event; 是否超时
    } timers[MAX_TIMERS];    /* set of timers */
    

     

     

    每一种反应计时器都以那几个数据结构来描述,第一个成员用来陈说石英钟是不是正在利用,第三个分子是其一计时器的定期时间,第多少个成员是是二个指针,*event开端化应为0,当她被置为1,大家领悟这些机械漏刻已经晚点了,和她有关的职分能够进行。

     

    接下去是沙漏数组的最初化,这里将种种石英钟inuse成员设置为FALSE,表示机械钟不可用。

    void
    timers_init() {
    struct timer *t;
    
    for (t=timers;t<&timers[MAX_TIMERS];t  )
    t->inuse = FALSE;
    }
    

     

    今天初叶是结构完毕部分

    第风姿浪漫写到的timer_undeclare这一个函数,这几个函数与背后的timer_declare绝争持。主要作用是去掉叁个沙漏。

    有为数不菲艺术能够用来保存反应计时器的准期记录。未有复杂机械钟硬件的机械日常在每三个时钟周期管理五个间断管理程序。然后软件就在管理程序中拿走系统时间,然后剖断是还是不是设置的停车计时器超时。

    洋洋相比较聪明的机械能够在硬件中装置定期时间,生机勃勃旦时间超时,就接触一个硬件中断。那同大器晚成适用与软件中断。

    他俩通过三个定义贰个time_now来记录当前的体系时间,volatile告诉机器每一趟从寄放器取值,防止数据被系统优化。

    volatile TIME time_now
    

     

    接下去定义一名目繁大多据来记录 timer_next 指接下来要大家想要计时的停车计时器。time_timer_set保存最终贰次拿到的种类时间。

    struct timer *timer_next = NULL;/* timer we expect to run down next */
    TIME time_timer_set;    /* time when physical timer was set */
    
    //取消一个定时器
    void timer_undeclare(struct timer *t)
    {
      disable_interrupts();
      if(!t->inuse)
      {
        enable_interrupts();
        return ;
      }
      t->inuse=0;
      if(t==timer_next)
      {
        if(time(&time_now)<0)
        perror("time error");
        timers_update(time_now-time_timer_set);    
        if(timer_next)
        {
          start_physical_timer(&timer_next->time);
          time_timer_set=time_now;
        }
      }
      enable_interrupts();
    
    }
    

     

    timer_undeclare作用为收回二个机械漏刻。首先让中断失效,那很要紧,因为时钟数据结构数据是在各进程中国共产党享的,是足以在别的中断中被涂改的,为了幸免不须求的错笔者,这些废除操作应为叁个原子操作。开头大家先检查测量试验是不是这么些时钟已经不行了。借使可行,则设置inuse使其失效。假若我们要撤回的电磁打点计时器适逢其时是下三个目的在于等待的沙漏。那大家要双重钦命下几个希望等待的电磁打点计时器。早先全部计时器都要翻新一下前贰个停车计时器已经渡过的时日。

     

    接下去大家来看timers_update(time_t ti)函数

     

    //更新定时器表时间
    void timers_update(time_t time)
    {
      static struct timer timer_last={
      0,
      {},
      NULL
      };
      timer_last.time.tv_sec=10;
    
    
    
      struct timer *t;
    
    
    
      timer_next=&timer_last;
    
    
    
      for(t=timers;t<&timers[MAX_TIMERS];t  )
      {
        if(t->inuse)
        {
          if(time<t->time.tv_sec){
          t->time.tv_sec-=time;
          if(t->time.tv_sec<
          timer_next->time.tv_sec)
            timer_next=t;
          }else
          {
            *(t->event)=1;
            t->inuse=0;
          }
        }
      }
      if(!timer_next->inuse)timer_next=0;
    }
    

     

    此函数成效是翻新具备有效反应计时器的时刻长,同临时间将timer_next指向当前延时光阴最短的三个电磁打点计时器。如未有机械漏刻,则将timer_next设置为空。

    timer_declare 参预三个电磁打点计时器 

    struct timer * timer_declare(TIME *ti,char *event)
    {
      struct timer *t;
      disable_interrupts();
    
      for(t=timers;t<&timers[MAX_TIMERS];t  )
      {
        if(!t->inuse)break;
      }
    
      if(t==&timers[MAX_TIMERS])
      {
        enable_interrupts();
        return 0;
      }
    
      t->event=event;
      t->time.tv_sec=ti->tv_sec;
      t->time.tv_usec=ti->tv_usec;
      if(!timer_next)
      {
    
        if(time(&time_now)<0)
        perror("time() error");
        time_timer_set=time_now;
        start_physical_timer(&((timer_next=t)->time));    
      }else if((ti->tv_sec time_now)<(
      timer_next->time.tv_sec time_timer_set))
      {
        if(time(&time_now)<0)
        perror("time error");
        timers_update(time_now-time_timer_set);
        time_timer_set=time_now;
        start_physical_timer(&((timer_next=t)->time));
      }else
      {
    
      }
      t->inuse=1;
      enable_interrupts();
      return t;
    }
    

     

    第后生可畏找到一个可用的计时器表项,设置相关参数。

    接下去推断如若timer_next为空,那么评释计时器表项未有电火花计时器须求定期,那我们平昔将timer_next指向新出席沙漏,开头计时。

    如果新加盟反应计时器须要延时时间比这段日子正在延时的沙漏的剩余时间还要短,则更新计时器表,并计时当前出席的放大计时器。

    在拍卖完当前电火花计时器事件后,将新参预的电火花计时器的inuse置1.

     

    接下去是沙漏中断管理函数

    //定时器中断处理函数
    void timer_interrupt_hander(int signo)
    {
      printf("interrupt_handern");
      if(time(&time_now)<0)
        perror("time() error");
      timers_update(time_now-time_timer_set);
    
      if(timer_next)
      {
        time_timer_set=time_now;
        start_physical_timer(&timer_next->time);    
      }
    }
    

     

    这里大家打字与印刷后生可畏串字符来证明电磁打点计时器时间的接触,首先要做的先更新计时器表,然后将time_timer_set设置成当前系统时间,继续举办下三个沙漏事件,直到全体沙漏都管理完毕。

     

    接下去几个是LINUX系统相关函数

    //失效定时器中断
    void disable_interrupts()
    {
    sigset_t new_mask;
    
    sigemptyset(&new_mask);
    sigaddset(&new_mask,SIGALRM);
    
    if(sigprocmask(SIG_BLOCK,&new_mask,NULL)<0)
    perror("SIG_BLOCK error");
    }
    
    //使能定时器中断
    void enable_interrupts()
    {
    sigset_t new_mask;
    
    sigemptyset(&new_mask);
    sigaddset(&new_mask,SIGALRM);
    if(sigprocmask(SIG_UNBLOCK,&new_mask,NULL)<0)
    perror("SIG_UNBLOCK error");
    }
    
    //开启一个定时器工作
    void start_physical_timer(TIME* time)
    {
    if(signal(SIGALRM,timer_interrupt_hander)==SIG_ERR)
    perror("signal error");    
    struct itimerval new_value;
    sigset_t zero_mask;
    sigemptyset(&zero_mask);
    
    new_value.it_value.tv_sec=time->tv_sec;
    new_value.it_value.tv_usec=time->tv_usec;
    new_value.it_interval.tv_sec=0;
    new_value.it_interval.tv_usec=0;
    setitimer(ITIMER_REAL,&new_value,NULL);
    sigsuspend(&zero_mask);
    }
    

     

     

    主函数测量检验部分

    #include<stdio.h>
    #include<signal.h>
    #include"multtime.h"
    #include<stdlib.h>
    #include<unistd.h>
    
    
    int main()
    {
        pid_t pid;
        TIME time1,time2,time3;
        time1.tv_sec=6;
        time1.tv_usec=0;
    
        time2.tv_sec=4;
        time2.tv_usec=0;
    
        time3.tv_sec=2;
        time3.tv_usec=0;
        timer_init();
        if((pid=fork())<0)
        {
            perror("fork() error");
        }
        else if(pid==0)
        {
            printf("child 1n");
            timer_undeclare(timer_declare(&time1,0));
        }
        else 
        {    
            if((pid=fork())<0)
            {
                perror("fork error");
            }
            else if(pid==0)
            {
                printf("child 2n");
                timer_undeclare(timer_declare(&time3,0));
            }
            else
            {
                printf("parentn");
                timer_undeclare(timer_declare(&time2,0));
            }
        }
    
    
        exit(0); 
    }
    

    推行结果:

    parent
    child 2
    child 1
    interrupt_hander
    interrupt_hander
    interrupt_hander
    

     

    自小编初学LINUX是个新手,以投机的知道写的,待浓厚学习后再完美修改。

     

     

     

    本例子参谋Don Libes的Title: Implementing Software Timers例子改写 为啥须要以此功...

    【Linux操作系统一分配析】准期度量——RTC,TSC,PIT,jiffies,计时体系布局,延迟函数

     

     

    1 基本概念

    按期体制及其一些更可以知道的基本活动(如检查超时卡塔尔国来促使进度切换。

    三种关键的依期测量:

     

    • 保留当前的年月和日期,以便能通过time(), ftime()和gettimeofday()系统调用把它们重临给客商程序。
    • 维持计时器,这种机制能够告诉内核或顾客程序某有时间间隔已经一瞑不视了。

     

    准期度量是由基于固定频率振荡器和计数器的几个硬件电路实现的。

     

     

    2 时钟和电磁打点计时器电路

    石英表电路用于追踪当前光阴和爆发正确的时日度量。

    计时器电路由根基编制程序,所以它们以udingde,预先定义的频率发出中断。

    石英电子手表电路的分类

     

    • 用于追踪当前时刻
      • 实时石英钟RTC
      • 时光戳计数器TSC
    • 发生周期性的石英钟中断,用于计时
      • 可编制程序间距停车计时器PIT

     

    为啥须求以此功能,因为大多数应用程式石英钟系统平时只好有多个石英钟触发三次暂停。当运转三个职分时,大家会想要七个反应计时器的石英钟追踪并发那样能够生成不易的时间重叠,操作系统这样做。

    2.1 实时时钟RTC——I奥迪Q5Q8上产生中断

    当PC被割裂电源,RTC还三回九转工作。

    底蕴通过0x70和0x71I/O端口访谈RTC。

    能在IXC90Q8上发出周期性的制动踏板,频率在2HZ~8192HZ之间,可编程

     

    2.2 时间戳流速计TSC

    在80x86微机中,有多个CLK输入引线接纳外界振荡器的机械钟时限信号。TSC在每种石英钟非确定性信号到来时加1.

    TSC是四个60位的小运戳流速計存放器,汇编指令rdtsc读这些寄放器。Linux在开头化时系统时必得分明石英钟非确定性信号的功效。

    新葡亰496net 1

     

    获取tsc的时钟频率:calibrate_tsc()函数通过测算多个大概在5ms的时光间距内所发出的电子机械表时限信号的个数来算出CPU实际频率。

    Linux通过rdtscll()或rdtscl()用来读取TSC的事。

    与可编制程序间距沙漏比较,TSC能够获取更可信的石英钟。

     

    本例子是为着落到实处利用Linux下的三个电磁打点计时器,完结任生龙活虎数量的电火花计时器功效。

    2.3 可编制程序间距停车计时器PIT

    使用I/O端口0x40~0x43

    LInux给PC的率先个PIT实行编制程序,使它以超越1000Hz的频率向IENCOREQ0发出挂钟中断,即每1ms发生三次石英钟中断,这些时辰间距叫做四个旋律(tick),它的长度以飞秒为单位寄存在tick_nsec变量中。

     

    新葡亰496net 2

     

     

    由setup_pit_timer()实行初阶化。在init_新葡亰496net,pit_timer()中起头化时钟中断频率。

    与系统石英钟随机信号有关的宏定义:

    (1)宏定义Hz

    在差别的体系机构下,系统时钟所要求的可编制程序定时器中断的成效,即每秒tick的个数

    (2)宏定义CLOCK_TICK_RATE

    记录了不相同连串布局下,驱动可编制程序测量时间的装置职业的输入时钟频率

    (3)宏定义LATCH

    笔录了上述七个宏定义的比率,用于在基本开首化进度中装置可编制程序反应计时器中流量计贮存器counter的伊始值。

     

    第大器晚成大家供给一些数据类型用来说述石英钟数据结构

    3 Linux计时系统布局

    LInux的计时类别布局是风度翩翩组与时光流相关的基本数据结会谈函数。

    功能:

     

    • 更新自系统运营以来所通过的岁月
    • 立异时间和日期
    • 明确当前经过的实施时间,思索是还是不是要抢占
    • 校订财富选拔总括计数
    • 自己商议到期的软反应计时器

     

    根基有两此中央的计时函数:

     

    • 维持最近新型的时刻
    • 估测计算在当前秒内迈过的皮秒数

     

    在单微处理机系统中,全数按期运动都由IHighlanderQ0上的机械手表中断触发,富含:

     

    • 在暂停中及时实施的一对
    • 作为下半部分延缓试行的有的

     

    #include <stdio.h>
    
    #include<time.h>
    
    #define TRUE 1
    #define FALSE    0
    
    #define MAX_TIMERS    ...    最大时钟数量
    typedef timerval TIME; 定义时间类型
    #define VERY_LONG_TIME    ... 最大时间长度
    
    struct timer {
    int inuse;    时钟是否可用
    TIME time; 定时时间长度
    char *event; 是否超时
    } timers[MAX_TIMERS];    /* set of timers */
    

    3.1 计时类别布局的数据结构

     

    3.1.1电磁打点计时器对象(机械钟源卡塔 尔(阿拉伯语:قطر‎

    为了利用意气风发种统后生可畏的方法来拍卖大概存在的机械漏刻财富,内核使用能够了“计时器对象”,它是timer_opts类型的贰个陈诉符。当中最重要的七个办法:

     

    mark_offset:由石英钟中断管理程序调用,并以适当的数据结构记录每种节拍到来时的准确时间。

    get_offset:使用已记录的值来总结上叁遍石英钟中断(节拍卡塔尔以来通过的时日。

    这三种艺术,使得Linuxd计时系统布局能够打到子节拍的分辨率,约等于说,内核能够以比节拍周期更加高的精度来测定当前的时日,这种操作被叫作“准期插补”。

     

    在根本初步化时期,select_timer()函数设置cur_timer指向适当沙漏对象(石英钟源卡塔尔国的地点。变量timer_cur寄存了有个别电磁打点计时器对应的格外之处,该沙漏是系统可应用的计时器能源中最棒的。

     

    新葡亰496net 3

     

     

     

    3.1.2jiffies变量

    三个流量计,用来记录自系统运转以来发出的点子总量。

    因为大器晚成分钟内发出系统石英钟中断次数等于宏定义HZ的值,所以变量jiffies的值在生龙活虎秒内扩张HZ。

     

    每种计时器都是这几个数据结构来陈说,第叁个成员用来陈说时钟是不是正在利用,第三个分子是其一反应计时器的定期时间,第七个成员是是多个指南针,*event初步化应为0,当他被置为1,大家精晓那么些停车计时器已经过期了,和她有关的职分能够施行。

    3.1.3xtime变量

    xtime变量存放当前些天子和日期,它是一个timespec类型的数据结构。以便内查对少数对象和事件作时间标志,如记录文件的开创时间、校订时间、上次访问时间,也许供客商进度经过系统调用来行使。

    着力每种tick更新三回。

     

     

    3.2 单微电脑系统上的计时类别布局

    考点:tick_handle_periodic函数的效应(Linux的计时种类布局的效益卡塔尔国

    新葡亰496net 4

    tick_init调用clockevents_tegister_notifier注册tick_notifier到clockevents_chain上。

    Update_wall_time()完毕变量xtime的改进。

    time_init_hook()来设置系统石英钟中断处理程序。

     

    在时钟中断管理函数中:

    会调用tick_init函数,书上超多流水生产线中的函数最后都是被那些函数所调用,流程如下:

    新葡亰496net 5

     

    接下去是沙漏数组的先河化,这里将种种挂钟inuse成员设置为FALSE,表示时钟不可用。

    4 软机械漏刻和延缓函数

    软沙漏:

     

    • 动态电火花计时器(内核卡塔尔
    • 间距沙漏(能够客户卡塔 尔(阿拉伯语:قطر‎

     

    动态沙漏:被动态的创设和注销,当前活动的动态沙漏个数未有节制

    沙漏是大器晚成种软件功效,即允许在明天的有个别时刻,函数在给定的小运间隔用完时被调用。每一个放大计时器都包罗一个字段,表示电火花计时器将索要多久才到期。那一个字段的初值正是jiffies的前段时间值加上适当的节拍数。

    潜心,对于必需从严据守定期时间的那多少个实时应用来说,停车计时器并不切合,因为沙漏的检讨一而再连续由可延迟函数实行。

     

    新葡亰496net 6

    void
    timers_init() {
    struct timer *t;
    
    for (t=timers;t<&timers[MAX_TIMERS];t  )
    t->inuse = FALSE;
    }
    

    4.1创制并激活二个动态电火花计时器——init_timer早先化叁个time_list对象

     

    • 创制叁个新的timer_list对象
    • 调用init_timer初步化,并安装计时器要拍卖的函数和参数
    • 设置准期时间
    • 使用add_timer参与到合适的链表中

    实际的步调:

    新葡亰496net 7

     

     

    4.2动态反应计时器的数据结构

    用于和系统核心变量jiffies进行比较。

    • 分子变量function:该函数指针变量保存了水源停车计时器超时后要试行的函数,即计时器超时管理函数。
    • 分子变量data:该无符号长整型变量用作电火花计时器超时处理函数的参数。
    • 分子变量base:该指针变量申明了该内核测量时间的装置节点归属于系统中哪一个微处理机,在选取函数init_timer()伊始化内核停车计时器节点的进度中,将该指针指向了八个每微处理机变量tvec_bases的积极分子变量t_base。

    近来起始是结构完毕部分

    4.3动态定时器的有限补助

    新葡亰496net 8

    run_timer的首要成效

     

    • 计时器时间表示参数加风流倜傥
    • 管理的沙漏去除
    • 依次拍卖到期反应计时器

     

    动态电火花计时器应用之delayed work

    动态停车计时器应用之schedule_timeout:  setup_time_on_stack(&timer, process_timeout, (unsigned long)current);  timer时间到了今后,process_timeout函数将这段日子进度变为等待态。

      

    第意气风发写到的timer_undeclare那么些函数,那几个函数与背后的timer_declare绝周旋。首要职能是清除一个电磁打点计时器。

    4.4延缓函数:

    当内核供给等待三个超级短的年月间距,如几纳秒,平常设备驱动器会等待预先定义的上上下下飞秒直到硬件完结有些操作。这几个境况下,内核使用udelay()和ndelay()函数:前面三个选取贰个阿秒级的时刻间隔作为它的参数,并在钦定的延迟甘休后归来,前面一个与前面八个相仿,可是钦赐延迟的参数是飞秒级的。

    有多数主意能够用来保存放大计时器的准期记录。未有复杂石英钟硬件的机器平常在每一个时钟周期管理一个暂停管理程序。然后软件就在管理程序中拿走系统时间,然后判别是或不是设置的计时器超时。

    不菲比较明白的机器能够在硬件中安装准期时间,生龙活虎旦时间超时,就接触二个硬件中断。那等同适用与软件中断。

    Linux计时系统布局,LINUX使用贰个放大计时器达成设置自便数量测量时间的装置。她俩经过一个定义三个time_now来记录当前的种类时间,volatile告诉机器每一回从存放器取值,幸免数据被系统优化。

    volatile TIME time_now
    

     

    接下去定义风流罗曼蒂克种类数据来记录 timer_next 指接下来要大家想要计时的反应计时器。time_timer_set保存最终二回拿到的系统时间。

    struct timer *timer_next = NULL;/* timer we expect to run down next */
    TIME time_timer_set;    /* time when physical timer was set */
    
    //取消一个定时器
    void timer_undeclare(struct timer *t)
    {
      disable_interrupts();
      if(!t->inuse)
      {
        enable_interrupts();
        return ;
      }
      t->inuse=0;
      if(t==timer_next)
      {
        if(time(&time_now)<0)
        perror("time error");
        timers_update(time_now-time_timer_set);    
        if(timer_next)
        {
          start_physical_timer(&timer_next->time);
          time_timer_set=time_now;
        }
      }
      enable_interrupts();
    
    }
    

    Linux计时系统布局,LINUX使用贰个放大计时器达成设置自便数量测量时间的装置。 

    timer_undeclare效率为收回二个沙漏。首先让中断失效,那相当重视,因为机械钟数据结构数据是在各进度中国共产党享的,是足以在任何中断中被改正的,为了制止不要求的错小编,那几个撤消操作应为三个原子操作。起初大家先检查测量试验是还是不是这些石英钟已经不著见效了。假如可行,则设置inuse使其失效。假使大家要撤回的机械漏刻适逢其时是下一个愿意等待的停车计时器。那大家要重复钦命下二个企盼等待的电火花计时器。以前全部反应计时器都要翻新一下前四个电磁打点计时器已经迈过的时刻。

     

    接下去我们来看timers_update(time_t ti)函数

     

    //更新定时器表时间
    void timers_update(time_t time)
    {
      static struct timer timer_last={
      0,
      {},
      NULL
      };
      timer_last.time.tv_sec=10;
    
    
    
      struct timer *t;
    
    
    
      timer_next=&timer_last;
    
    
    
      for(t=timers;t<&timers[MAX_TIMERS];t  )
      {
        if(t->inuse)
        {
          if(time<t->time.tv_sec){
          t->time.tv_sec-=time;
          if(t->time.tv_sec<
          timer_next->time.tv_sec)
            timer_next=t;
          }else
          {
            *(t->event)=1;
            t->inuse=0;
          }
        }
      }
      if(!timer_next->inuse)timer_next=0;
    }
    

     

    此函数功能是翻新具备有效计时器的小时长,同期将timer_next指向当前延时日子最短的七个电磁打点计时器。如未有电磁打点计时器,则将timer_next设置为空。

    timer_declare 参加二个计时器 

    struct timer * timer_declare(TIME *ti,char *event)
    {
      struct timer *t;
      disable_interrupts();
    
      for(t=timers;t<&timers[MAX_TIMERS];t  )
      {
        if(!t->inuse)break;
      }
    
      if(t==&timers[MAX_TIMERS])
      {
        enable_interrupts();
        return 0;
      }
    
      t->event=event;
      t->time.tv_sec=ti->tv_sec;
      t->time.tv_usec=ti->tv_usec;
      if(!timer_next)
      {
    
        if(time(&time_now)<0)
        perror("time() error");
        time_timer_set=time_now;
        start_physical_timer(&((timer_next=t)->time));    
      }else if((ti->tv_sec time_now)<(
      timer_next->time.tv_sec time_timer_set))
      {
        if(time(&time_now)<0)
        perror("time error");
        timers_update(time_now-time_timer_set);
        time_timer_set=time_now;
        start_physical_timer(&((timer_next=t)->time));
      }else
      {
    
      }
      t->inuse=1;
      enable_interrupts();
      return t;
    }
    

     

    先是找到一个可用的沙漏表项,设置相关参数。

    接下去决断假设timer_next为空,那么评释机械漏刻表项没有电磁打点计时器需求依期,那我们直接将timer_next指向新步入机械漏刻,开端计时。

    假定新参加电磁打点计时器供给延时岁月比当下正值延时的放大计时器的剩余时间还要短,则更新反应计时器表,并计时当前投入的放大计时器。

    在拍卖完当前电火花计时器事件后,将新走入的停车计时器的inuse置1.

     

    接下去是电磁打点计时器中断管理函数

    //定时器中断处理函数
    void timer_interrupt_hander(int signo)
    {
      printf("interrupt_handern");
      if(time(&time_now)<0)
        perror("time() error");
      timers_update(time_now-time_timer_set);
    
      if(timer_next)
      {
        time_timer_set=time_now;
        start_physical_timer(&timer_next->time);    
      }
    }
    

     

    此地我们打字与印刷朝气蓬勃串字符来证实反应计时器时间的触发,首先要做的先更新电火花计时器表,然后将time_timer_set设置成当前系统时间,继续打开下叁个电火花计时器事件,直到全体沙漏都管理完成。

     

    接下去几个是LINUX系统相关函数

    //失效定时器中断
    void disable_interrupts()
    {
    sigset_t new_mask;
    
    sigemptyset(&new_mask);
    sigaddset(&new_mask,SIGALRM);
    
    if(sigprocmask(SIG_BLOCK,&new_mask,NULL)<0)
    perror("SIG_BLOCK error");
    }
    
    //使能定时器中断
    void enable_interrupts()
    {
    sigset_t new_mask;
    
    sigemptyset(&new_mask);
    sigaddset(&new_mask,SIGALRM);
    if(sigprocmask(SIG_UNBLOCK,&new_mask,NULL)<0)
    perror("SIG_UNBLOCK error");
    }
    
    //开启一个定时器工作
    void start_physical_timer(TIME* time)
    {
    if(signal(SIGALRM,timer_interrupt_hander)==SIG_ERR)
    perror("signal error");    
    struct itimerval new_value;
    sigset_t zero_mask;
    sigemptyset(&zero_mask);
    
    new_value.it_value.tv_sec=time->tv_sec;
    new_value.it_value.tv_usec=time->tv_usec;
    new_value.it_interval.tv_sec=0;
    new_value.it_interval.tv_usec=0;
    setitimer(ITIMER_REAL,&new_value,NULL);
    sigsuspend(&zero_mask);
    }
    

     

     

    主函数测量检验部分

    #include<stdio.h>
    #include<signal.h>
    #include"multtime.h"
    #include<stdlib.h>
    #include<unistd.h>
    
    
    int main()
    {
        pid_t pid;
        TIME time1,time2,time3;
        time1.tv_sec=6;
        time1.tv_usec=0;
    
        time2.tv_sec=4;
        time2.tv_usec=0;
    
        time3.tv_sec=2;
        time3.tv_usec=0;
        timer_init();
        if((pid=fork())<0)
        {
            perror("fork() error");
        }
        else if(pid==0)
        {
            printf("child 1n");
            timer_undeclare(timer_declare(&time1,0));
        }
        else 
        {    
            if((pid=fork())<0)
            {
                perror("fork error");
            }
            else if(pid==0)
            {
                printf("child 2n");
                timer_undeclare(timer_declare(&time3,0));
            }
            else
            {
                printf("parentn");
                timer_undeclare(timer_declare(&time2,0));
            }
        }
    
    
        exit(0); 
    }
    

    实验结果:

    parent
    child 2
    child 1
    interrupt_hander
    interrupt_hander
    interrupt_hander
    

     

    本人初学LINUX是个新手,以和谐的接头写的,待深切学习后再通盘更改。

     

     

     

    本文由新葡亰496net发布于电脑系统,转载请注明出处:Linux计时系统布局,LINUX使用贰个放大计时器达成

    关键词: