原创 Linux 环境下定时器实验

2009-12-17 17:08 2968 2 2 分类: MCU/ 嵌入式

<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />

 

一、实验目的


1、掌握 Linux 下的定时编程方法;


2、掌握 Linux 下的常用间函数编程方法。


二、实验内容


1、编写定器程序 timer


2、编写 Makefile 文件;


3、下载并 timer



三、预备知识


1C 语言基础知识;


2、程序调的基础知识和方法;


3Linux 基本操作;


4、掌握 Linux 下的程序译与交叉编译过程;


5、掌握 Linux 下基本的用程序编写方法。


四、基础知识


操作系统应该能够在将来某个时刻准时调度某个任务。所以需要一种能保证任务较准 时调度运行的机制。希望支持每种操作系统的微处理器必须包含一个可周期性中断它的可 编程间隔定时器。这个周期性中断被称为系统时钟滴答,它象节拍器一样来组织系统任务。 Linux 的时钟观念很简单:它表示系统启动后的以时钟滴答记数的时间。所有的系统时钟都基于这种量度,在系统中的名称和一个全局变量相同-jiffies


Linux 包含两种类型的系统定时器,它们都可以在某个系统时间上被队列例程使用, 但是它们的实现稍有区别。


第一个是老的定时器机制,它包含指向 timer_struct 结构的 32 位指针的静态数组以当 前活动定时器的屏蔽码:time_active


此定时器表中的位置是静态定义的(类似底层部分处理表 bh_base)。其入口在系统初 始化时被加入到表中。第二种是相对较新的定时器,它使用一个到期时间以升序排列的 timer_list 结构链表。


这两种方法都使用 jiffies 作为终结时间,这样希望运行 5 秒的定时器将不得不将 5 时间转换成 jiffies 的单位并且将它和以 jiffies 记数的当前系统时间相加从而得到定时器的 终结时间。在每个系统时钟滴答时,定时器的底层部分处理过程被标记成活动状态以便调 度管理器下次运行时能进行定时器队列的处理。定时器底层部分处理过程包含两种类型的 系统定时器。老的系统定时器将检查 timer_active 位是否置位。如果活动定时器已经到期则其定时器例程将被调用同时它的活动位也被清除新定时 器位于 timer_list 结构表中的入口也将受到检查。每个过期定时器将从链表中清除,同时 它的例程将被调用。新定时器机制的优点之一是能传递一个参数给定时器例程。


、实验说明


在本实验应用程序中,需要进行时间相关的编程动作,如获取当前时间,对某一段工 作进行计时处理以及定时执行某一动作等。本实验将介绍如何在 Linux 调用时间相关函数 完成上述功能。


1、  获取当前时间 在程序当中,可以使用下面两个函数输出系统当前的时间:


 time_t time(time_t*tloc)


char*ctime(const time_t *clock)


time 函数返回从 <?xml:namespace prefix = st1 ns = "urn:schemas-microsoft-com:office:smarttags" />1970 1 1 0 点以来的秒数.存储在 time_t 结构之中.这个函 数的返回值由于不够直观,以人类的理解方式,这组抽象的数字似乎缺乏实际意义。所以 我们可以另一个函数 ctime(const time_t *clock)将抽象的时间记录转化为直观的字符串, 以便显示。


2、  计时处理


有时候我们要计算程序执行的时间。比如我们要对算法进行时间分析。这个时候可以使用下面这个函数,加在需要计算时间的程序的两端:


int gettimeofday(struct timeval*tvstruct timezone*tz)


第一个参数为 timeval 类型的结构,该结构声明如下:


Strut timeval{


Long tv_sec; //秒数


Long tv_usec;    //


}


gettimeofday 将时间保存在结构 tv 之中。


3、  定时器


Linux 操作统为每一个进程提供了 3 个内部间计时器。 ITIMER_REAL:减少实际时间。到时的时候发出 SIGALRM 信号。 TIMER_VIRTUAL有效时间(进程执行的时间)到时时候产生 SIGVTALRM信号。


ITIME_PROF:减少进程的有效时间和系统时间(为进程调度用的时间)。到时的时候产生 SIGPROF 信号。


具体的操作函数是:


int getitimer(int whichstruct  itimerval*value)


int setitimer(int whichstruct  itimerval*newvalstruct itimerval*oldval)


相关结构类型声明如下:


struct itimerval{


struct timeval it_interval


struct timeval it value


}


getitimer 函数得到间隔计时器的时间值并保存在 value 中。setitimer 函数设置间隔计 时器的时间值为 newval,并将旧值保存在 oldval 中。which 表示使用三个计时器中的哪一 个。itimerval 结构中的 it_value 是减少的时间,当这个值为 0 的时候就发出相应的信号了,然后设置为 it_interval 值。


六、实验步骤


编写 timerc 程序源代码


#include <stdio.h>


#include <sys/time.h>


#include <signal.h>


 


 


struct timeval tpstart,tpend;


float   timeuse;


static timer_count = 0;


 


 


void prompt_info(int signo)


{


time_t t = time(NULL);


/* [1] 2 seconds turned, print something */


printf("[%d] prompt_info called\n", ++timer_count);


/* [2] get current time and print it */


ctime(&t);


printf(" current time %s", ctime(&t));


/* [3] stop get time, and print it */


gettimeofday(&tpend,NULL);


timeuse=1000000*(tpend.tv_sec-tpstart.tv_sec)+tpend.tv_usec-tpstart.tv_usec;


timeuse/=1000000;


printf(" Used Time:%f\n",timeuse);


}


 


 


void init_sigaction(void)


{


struct sigaction act; act.sa_handler=prompt_info; act.sa_flags=0; sigemptyset(&act.sa_mask); sigaction(SIGPROF,&act,NULL);


 


 


/* begin get the time */ gettimeofday(&tpstart,NULL); printf("begin time\n");


}


void init_time()


{


struct itimerval value; value.it_value.tv_sec=2; value.it_value.tv_usec=0; value.it_interval=value.it_value; setitimer(ITIMER_PROF,&value,NULL);


}


 


 


/*


* timer application code


*/


int main(int argc, char **argv)


{


init_sigaction(); init_time(); while(1); exit(0);


}


3、编写 Makefile 文件,Makefile 内容如下:


CC=gcc


LD=ld


 


EXEC = timer


OBJS = timer.o


 


 


CFLAGS += LDFLAGS +=


 


 


all: $(EXEC)


 


 


$(EXEC): $(OBJS)


$(CC) $(LDFLAGS) -o $@ $(OBJS) $(LDLIBS$(LDLIBS_$@))


 


 


clean:


-rm -f $(EXEC) *.elf *.gdb *.o


4、编译timer,在timer录下,终端输入如下命令:


# make clean


# make


# ./timer


结果如下:


[1] prompt_info called


current time Sat Mar 30 15:58:23 2005


Used Time:2.003054


[2] prompt_info called


current time Sat Mar 30 15:58:25 2005


Used Time:4.001216


[3] prompt_info called


current time Sat Mar 30 15:58:27 2005


Used Time:6.001144


[4] prompt_info called


current time Sat Mar 30 15:58:29 2005


Used Time:8.001138


该程序正确执行时将每隔两秒钟打印一次上述信息,“prompt_info  called”字符串是在定时器处理函数中打印的,还打印了当前系统时间和从第 1 次启动定时器开始获取的时 间间隔。


 


 


 


 


 


 


 


 


 


 


 


 


 


 


 


 


 

PARTNER CONTENT

文章评论0条评论)

登录后参与讨论
EE直播间
更多
我要评论
0
2
关闭 站长推荐上一条 /3 下一条