Chinaunix首页 | 论坛 | 博客
  • 博客访问: 189806
  • 博文数量: 46
  • 博客积分: 1355
  • 博客等级: 中尉
  • 技术积分: 336
  • 用 户 组: 普通用户
  • 注册时间: 2010-05-02 16:20
文章分类

全部博文(46)

文章存档

2017年(2)

2014年(12)

2012年(1)

2011年(5)

2010年(26)

我的朋友

分类: LINUX

2010-08-31 11:37:03

定时器与时间管理:

1、节拍率——HZ:在alpha体系结构上1024,而在其它平台上,都为10数量级倍。在嵌入式ARM上为100(2.6内核)。这个值的意义是什么呢,也就是在ARM平台上时钟中断100次,为一秒。一般的情况下编程者不要改变这个值,因为内核编很多代码都是有时间要求的,而且内核编写都在很多地方都做了相应的优化与折衷处理,改变HZ的值会对系统的性能有很大的影响。

2jiffies:这个值是用来记录系统自系统启动以来产生的节拍的总数,启动时,内核将这个变量初始化为0;在每次的时钟中断处理程序都会增加该变量的值,jiffies一秒内增加的值就是HZ系统运行时间以秒为单位计算,则为系统运行了jiffies/HZ秒

如下定义(2.6内核):

extern u64 __jiffy_data jiffies_64;
extern unsigned long volatile __jiffy_data jiffies;

2.6的内核中它的变量类型从无符号长整型变为了u64,也就是说,即使是32位的机器,也使用无符号的64位整型表示jiffies。大多数的代码只涉及jiffies的低32位,访问jiffies的代码中会读到jiffies_64的低32位,可以通过get_ jiffies_64()函数读取整个64位。在64位的体系结构中jiffies_64jiffies指的同一个变量,代码可以既可以通过jiffies也可以通过get_ jiffies_64()读取。

3、为了避免jiffies值的回绕(溢出),内核中提供了几个API函数来比较节拍计数。定义在中。

/* time_is_before_jiffies(a) return true if a is before jiffies */
#define time_is_before_jiffies(a) time_after(jiffies, a)
/* time_is_after_jiffies(a) return true if a is after jiffies */
#define time_is_after_jiffies(a) time_before(jiffies, a) 
/* time_is_before_eq_jiffies(a) return true if a is before or equal to jiffies*/
#define time_is_before_eq_jiffies(a) time_after_eq(jiffies, a)
/* time_is_after_eq_jiffies(a) return true if a is after or equal to jiffies*/
#define time_is_after_eq_jiffies(a) time_before_eq(jiffies, a)

例:

 可以利用jiffies设置超时等,譬如:

unsigned long timeout = jiffies + HZ * 2; // 2秒钟后超时
       
if(time_before(jiffies, timeout){
       // 还没有超时
    }
    
else{
       // 已经超时
    }


4、时间类型

Linux下常用的时间类型有4个:time_tstruct timevalstruct timespecstruct tm。一般用于实际时间(墙上时间),定义在文件中。

1time_t是一个长整型,一般用来表示用1970年以来的秒数,格林威治时间。

2Struct timeval有两个成员,一个是秒,一个是微妙。

struct timeval{
            
long tv_sec; /**//* seconds */
            
long tv_usec; /**//* microseconds */
 
};

3struct timespec有两个成员,一个是秒,一个是纳秒。

struct timespec{

         time_t tv_sec; /**//* seconds */格林威治时间
         
long tv_nsec; /**//* nanoseconds */
 
};

4struct tm是直观意义上的时间表示方法:

struct tm {
        
int tm_sec; /**//* seconds */
        
int tm_min; /**//* minutes */
        
int tm_hour; /**//* hours */
        
int tm_mday; /**//* day of the month */
        
int tm_mon; /**//* month */
        
int tm_year; /**//* year */
        
int tm_yday; /**//* day in the year */
        
int tm_wday; /**//* day of the week */
        
int tm_isdst; /**//* daylight saving time */
 
};

:一般使用int gettimeofday(struct timeval *tv, struct timezone *tz);得到墙上时间,墙上时间一般会在用户空间里使用,而在内核空间里,大多数情况下只要获取相对时间就OK了,也就是说用jiffies搞定。

5、内核定时器

内核定时器可以理解为一个软件定时器,它可以被动态的创建、更改和销毁等,而且运行次数没有限制。

定时器同结构time_list表示,此结构体定义在中。

struct timer_list {
       
struct list_head entry; //包含定时器的链表
       
unsigned long expires; //以jiffies为单位的定时值
       
void (*function)(unsigned long); //定时时间到的处理函数
       
unsigned long data; //传给片处理函数的参数,可以用在共用一个处理函数的情况。
       
struct tvec_base *base; //内部值,用户呼略是安全的
#ifdef CONFIG_TIMER_STATS
       
void *start_site;
       
char start_comm[16];
       
int start_pid;
#endif
#ifdef CONFIG_LOCKDEP
       
struct lockdep_map lockdep_map;
#endif
};

在使用定时器时,没有必要去深入了解这个数据结构体的成员。可以使用在中的API来操作。

增加定时器

void add_timer(struct timer_list * timer);
删除定时器

int del_timer(struct timer_list * timer);
修改定时器的expire

int mod_timer(struct timer_list *timer, unsigned long expires);
使用定时器的一般流程为:
1)定义timer、编写function
2)为timerexpiresdatafunction赋值;
3)调用add_timertimer加入列表;
4)在定时器到期时,function被执行;
5)在程序中涉及timer控制的地方适当地调用del_timermod_timer删除timer或修改timerexpires
补充:一般应该使用del_timer_sync()来代替del_timer(),在俺的板子上就同没有必要了,因为俺的板子是单处理器的,在SMP中一定要代替使用。

6、短延迟

前面所讲到的时间都是很长的了啦,在内核中提供了二个更短延迟的函数来供开发人员使用

udelay(unsigned long usecs);   //微秒
mdelay(unsigned long msecs);  //
毫秒
前者用软件循环指定的微妙数,后者调用前者达到延迟毫秒级。udelay 函数只能用于获取较短的时间延迟,因为loops_per_second值的精度只有8位,所以,当计算更长的延迟时会积累出相当大的误差。尽管最大能允 许的延迟将近1(因为更长的延迟就要溢出),推荐的 udelay 函数的参数的最大值是取1000微秒(1毫秒)。延迟大于 11 毫秒时可以使用函数 mdelay
:要特别注意的是 udelay 是个忙等待函数(所以 mdelay 也是),在延迟的时间段内无法运行其他的任务,因此要十分小心,尤其是 mdelay,除非别无他法,要尽量避免使用。

 





阅读(3211) | 评论(1) | 转发(0) |
0

上一篇:Linux之并发与竞态

下一篇:Linux之内存管理

给主人留下些什么吧!~~

chinaunix网友2010-09-02 16:03:20

Download More than 1000 free IT eBooks: http://free-ebooks.appspot.com