国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁(yè) > 系統(tǒng) > Linux > 正文

Linux使用一個(gè)定時(shí)器實(shí)現(xiàn)設(shè)置任意數(shù)量定時(shí)器功能

2020-10-28 18:45:08
字體:
來(lái)源:轉(zhuǎn)載
供稿:網(wǎng)友

為什么需要這個(gè)功能,因?yàn)榇蠖鄶?shù)計(jì)算機(jī)軟件時(shí)鐘系統(tǒng)通常只能有一個(gè)時(shí)鐘觸發(fā)一次中斷。當(dāng)運(yùn)行多個(gè)任務(wù)時(shí),我們會(huì)想要多個(gè)定時(shí)器 的時(shí)鐘跟蹤并發(fā)這樣可以生成正確的時(shí)間重疊,操作系統(tǒng)這樣做。

本例子是為了實(shí)現(xiàn)使用Linux下的一個(gè)定時(shí)器,實(shí)現(xiàn)任一數(shù)量的定時(shí)器功能。

首先我們需要一些數(shù)據(jù)類(lèi)型用來(lái)描述時(shí)鐘數(shù)據(jù)結(jié)構(gòu)

#include <stdio.h>#include<time.h>#define TRUE 1#define FALSE 0#define MAX_TIMERS ... 最大時(shí)鐘數(shù)量typedef timerval TIME; 定義時(shí)間類(lèi)型#define VERY_LONG_TIME ... 最大時(shí)間長(zhǎng)度struct timer {int inuse; 時(shí)鐘是否可用TIME time; 定時(shí)時(shí)間長(zhǎng)度char *event; 是否超時(shí)} timers[MAX_TIMERS]; /* set of timers */

每個(gè)定時(shí)器都以這個(gè)數(shù)據(jù)結(jié)構(gòu)來(lái)描述,第一個(gè)成員用來(lái)描述時(shí)鐘是否正在使用,第二個(gè)成員是這個(gè)定時(shí)器的定時(shí)時(shí)間,第三個(gè)成員是是一個(gè)指針,*event初始化應(yīng)該為0,當(dāng)他被置為1,我們知道這個(gè)定時(shí)器已經(jīng)超時(shí)了,和他相關(guān)的任務(wù)可以執(zhí)行。

接下來(lái)是定時(shí)器數(shù)組的初始化,這里將每個(gè)時(shí)鐘inuse成員設(shè)置為FALSE,表示時(shí)鐘不可用。

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

現(xiàn)在開(kāi)始是結(jié)構(gòu)實(shí)現(xiàn)部分

首先寫(xiě)到的timer_undeclare這個(gè)函數(shù),這個(gè)函數(shù)與后面的timer_declare相對(duì)立。主要作用是清除一個(gè)定時(shí)器。

有很多方法可以用來(lái)保存定時(shí)器的定時(shí)記錄。沒(méi)有復(fù)雜時(shí)鐘硬件的機(jī)器通常在每一個(gè)時(shí)鐘周期處理一個(gè)中斷處理程序。然后軟件就在處理程序中獲取系統(tǒng)時(shí)間,然后判斷是否設(shè)置的定時(shí)器超時(shí)。

很多比較聰明的機(jī)器可以在硬件中設(shè)置定時(shí)時(shí)間,一旦時(shí)間超時(shí),就觸發(fā)一個(gè)硬件中斷。這同樣適用與軟件中斷。

他們通過(guò)一個(gè) 定義一個(gè)time_now來(lái)記錄當(dāng)前的系統(tǒng)時(shí)間,volatile告訴機(jī)器每次從寄存器取值,防止數(shù)據(jù)被系統(tǒng)優(yōu)化。

volatile TIME time_now 

接下來(lái)定義一系列數(shù)據(jù)來(lái)記錄 timer_next 指接下來(lái)要我們想要計(jì)時(shí)的定時(shí)器。time_timer_set保存最后一次獲取的系統(tǒng)時(shí)間。

struct timer *timer_next = NULL;/* timer we expect to run down next */TIME time_timer_set;  /* time when physical timer was set *///取消一個(gè)定時(shí)器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作用為取消一個(gè)定時(shí)器。首先讓中斷失效,這很重要,因?yàn)闀r(shí)鐘數(shù)據(jù)結(jié)構(gòu)數(shù)據(jù)是在各進(jìn)程中共享的,是可以在其他中斷中被修改的,為了防止不必要的錯(cuò)我,這個(gè)取消操作應(yīng)該為一個(gè)原子操作。開(kāi)始我們先檢測(cè)是否這個(gè)時(shí)鐘已經(jīng)無(wú)效了。如果有效,則設(shè)置inuse使其失效。如果我們要取消的定時(shí)器正好是下一個(gè)期望等待的定時(shí)器。那我們要重新指定下一個(gè)期望等待的定時(shí)器。在此之前所有定時(shí)器都要更新一下前一個(gè)定時(shí)器已經(jīng)走過(guò)的時(shí)間。

接下來(lái)我們看到timers_update(time_t ti)函數(shù)

//更新定時(shí)器表時(shí)間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;}

此函數(shù)作用是更新所有有效定時(shí)器的時(shí)間長(zhǎng),同時(shí)將timer_next指向當(dāng)前延時(shí)時(shí)間最短的一個(gè)定時(shí)器。如沒(méi)有定時(shí)器,則將timer_next設(shè)置為空。

timer_declare 加入一個(gè)定時(shí)器

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;}

首先找到一個(gè)可用的定時(shí)器表項(xiàng),設(shè)置相關(guān)參數(shù)。

接下來(lái)判斷如果timer_next為空,那么說(shuō)明定時(shí)器表項(xiàng)沒(méi)有定時(shí)器需要定時(shí),那我們直接將timer_next指向新加入定時(shí)器,開(kāi)始計(jì)時(shí)。

如果新加入定時(shí)器需要延時(shí)時(shí)間比當(dāng)前正在延時(shí)的定時(shí)器的剩余時(shí)間還要短,則更新定時(shí)器表,并計(jì)時(shí)當(dāng)前加入的定時(shí)器。

在處理完當(dāng)前定時(shí)器事件后,將新加入的定時(shí)器的inuse置1.

接下來(lái)是定時(shí)器中斷處理函數(shù)

//定時(shí)器中斷處理函數(shù)void timer_interrupt_hander(int signo){  printf("interrupt_hander/n");  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);    }}

這里我們打印一串字符來(lái)證明定時(shí)器時(shí)間的觸發(fā),首先要做的先更新定時(shí)器表,然后將time_timer_set設(shè)置成當(dāng)前系統(tǒng)時(shí)間,繼續(xù)進(jìn)行下一個(gè)定時(shí)器事件,直到所有定時(shí)器都處理完畢。

接下來(lái)幾個(gè)是LINUX系統(tǒng)相關(guān)函數(shù)

//失效定時(shí)器中斷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");}//使能定時(shí)器中斷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");}//開(kāi)啟一個(gè)定時(shí)器工作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);}

主函數(shù)測(cè)試部分

#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 1/n");    timer_undeclare(timer_declare(&time1,0));  }  else   {      if((pid=fork())<0)    {      perror("fork error");    }    else if(pid==0)    {      printf("child 2/n");      timer_undeclare(timer_declare(&time3,0));    }    else    {      printf("parent/n");      timer_undeclare(timer_declare(&time2,0));    }  }  exit(0); }

實(shí)驗(yàn)結(jié)果:

parentchild 2child 1interrupt_handerinterrupt_handerinterrupt_hander

總結(jié)

以上所述是小編給大家介紹的Linux使用一個(gè)定時(shí)器實(shí)現(xiàn)設(shè)置任意數(shù)量定時(shí)器功能,希望對(duì)大家有所幫助,如果大家有任何疑問(wèn)請(qǐng)給我留言,小編會(huì)及時(shí)回復(fù)大家的。在此也非常感謝大家對(duì)武林網(wǎng)網(wǎng)站的支持!

發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 滨海县| 拜泉县| 九江市| 平原县| 黔江区| 清原| 漳州市| 贞丰县| 高邑县| 佛冈县| 剑阁县| 沐川县| 牟定县| 夏邑县| 澎湖县| 江津市| 永登县| 荥阳市| 满洲里市| 肃北| 克山县| 广饶县| 滨海县| 镶黄旗| 大石桥市| 县级市| 绍兴市| 乐清市| 邢台市| 布尔津县| 山西省| 朝阳区| 赫章县| 北票市| 太湖县| 沂水县| 宝鸡市| 中牟县| 浑源县| 文昌市| 信丰县|