一.概念
1.从功能方面时钟分三种:计时,延时,定时器。
2.内核时钟:内核通过定时器(timer)中断来跟踪时间流,硬件定时器以周期性的间隔产生中断,这个时间间隔通常取1ms到10ms。
3.jiffies计算器:每次当定时器中断发生时,内核内部通过一个64位的变量jiffies_64做加一计数。
驱动程序开发者通常访问的是jiffies变量,它是jiffies_64的低32位。
jiffies是unsigned long型的变量,该变量被声明为volatile,这样可避免编译器对访问该变量的语句的优化 。
4.HZ:HZ即表示每秒钟产生的定时中断次数,HZ就代表1秒,HZ/2就代表0.5秒。
5.1s = 1HZ = 256jiffies(看具体内核)= 256次定时器中断
二.常见问题
1.内核定时器与tasklet比较相同点
在中断期间运行。始终会在调度他们的同一cpu上运行。软件中断上下文,原子模式运行。
2.内核定时器与tasklet比较不同点
不能要求TASKLET在给定的时间执行
3.重识TASKLET的特性
一个tasklet可在稍后被禁止或者重新启用;只有启用的次数和禁止的次数相同时,tasklet才会被执行。
a.和定时器类似,tasklet可以注册自己本身。
b.tasklet可被调度以在通常的优先级或者高优先级执行。高优先级的tasklet总会首先执行。
c.如果系统负荷不重,则tasklet会立即得到执行,但始终不会晚于下一个定时器滴答。
d.一个tasklet可以和其他tasklet并发,但对自身来讲是严格串行处理的,也就是说, 同一tasklet永远不会在多个处理器上同时运行。当然我们已经指出,tasklet始终会在调度自己的同一CPU上运行。
三.驱动模块功能相关的数据结构
1.jiffies计数器:全局变量
1)用户空间的timeval:
struct timeval {
time_t tv_sec; /* 秒 */
suseconds_t tv_usec; /* 毫秒 */
};
2)用户空间的timespec:
struct timespec {
time_t tv_sec; /* 秒 */
long tv_nsec; /* 纳秒 */
};
jiffies:可以实现计时等功能。可以知道当前内核"滴答"次数.
成员函数:#include<1inux/jiffies.h>
初始化:
功能函数;
a.jiffies计数器
current_j = jiffies; /*读取当前值*/
stamp_1 = current_j + HZ; /*未来的1秒*/
stamp_half = current_j + HZ/2; /*半秒*/
stamp_n = current_j + n*HZ/1000;/*n毫秒*/
b.比较时间量,比较节拍计数; a 宏名 b? 1:0.
int time_after(unsigned long a,unsigned long b);
int time_before(unsigned long a,unsigned long b);
int time_after_eq(unsigned long_a,unsigned long b);
int time_before_eq(unsigned long a,unsigned long b);
c.jiffies值和timeval、timespec之间转换
unsigned long timespec_to_jiffies(struct timespec *value);
void jiffies_to_timespec(unsigned long jiffie, struct timespec *value);
unsigned long timeval_to_jiffies(struct timeval *value);
void jiffies_to_timeval(unsigned long jiffies,struct timeval *value);
d.获取当前时间
void do_gettimeofday(struct timeval *tv);
struct timespec current_kernel_time(void);
延迟作用:让程序延迟执行
成员函数:#include<1inux/sched.h>
初始化:
功能函数;
a.长延时
set_current_state(TASK_INTERRUPTIBLE);
schedule_timeout(delay);
b.短延时#include <linux/delay.h>
void ndelay(unsigned long nsecs); /*延时纳秒*/
void udelay(unsigned long usecs); /*延时微妙*/
void mdelay(unsigned long msecs);/*延时毫秒*/
c.不使用忙等待的延迟方式
void msleep(unsigned int millisecs);
unsigned long msleep_interruptible(unsigned int millisecs);
释放资源:
典型应用:
while(time_before(jiffies,end_time)){
schedule();
struct timer_list{
/*…*/
unsigned long expires;
void (*function)(unsigned long);
unsigned long data;
};
内核定时器:产生定时器中断,写中断服务函数。例如实现按键中断。
成员函数:#include <linux/timer.h>
初始化:
a.这2个初始化不怎么好用
void init_timer(struct timer_list *timer);
struct timer_list TIMER_INITIALIZER(_function,_expires,_data);
功能函数;
a.添加,删除定时器到内核资源,执行完后自动移除定时器
void add_timer(struct timer_list *timer);
int del_timer(struct timer_list *timer);
b.其他
int mod_timer(struct timer_list *timer,unsigned long expires);
int del_timer_sync(struct timer_list *timer);
int timer_pending(const struct timer_list *timer);
1.从功能方面时钟分三种:计时,延时,定时器。
2.内核时钟:内核通过定时器(timer)中断来跟踪时间流,硬件定时器以周期性的间隔产生中断,这个时间间隔通常取1ms到10ms。
3.jiffies计算器:每次当定时器中断发生时,内核内部通过一个64位的变量jiffies_64做加一计数。
驱动程序开发者通常访问的是jiffies变量,它是jiffies_64的低32位。
jiffies是unsigned long型的变量,该变量被声明为volatile,这样可避免编译器对访问该变量的语句的优化 。
4.HZ:HZ即表示每秒钟产生的定时中断次数,HZ就代表1秒,HZ/2就代表0.5秒。
5.1s = 1HZ = 256jiffies(看具体内核)= 256次定时器中断
二.常见问题
1.内核定时器与tasklet比较相同点
在中断期间运行。始终会在调度他们的同一cpu上运行。软件中断上下文,原子模式运行。
2.内核定时器与tasklet比较不同点
不能要求TASKLET在给定的时间执行
3.重识TASKLET的特性
一个tasklet可在稍后被禁止或者重新启用;只有启用的次数和禁止的次数相同时,tasklet才会被执行。
a.和定时器类似,tasklet可以注册自己本身。
b.tasklet可被调度以在通常的优先级或者高优先级执行。高优先级的tasklet总会首先执行。
c.如果系统负荷不重,则tasklet会立即得到执行,但始终不会晚于下一个定时器滴答。
d.一个tasklet可以和其他tasklet并发,但对自身来讲是严格串行处理的,也就是说, 同一tasklet永远不会在多个处理器上同时运行。当然我们已经指出,tasklet始终会在调度自己的同一CPU上运行。
三.驱动模块功能相关的数据结构
1.jiffies计数器:全局变量
1)用户空间的timeval:
struct timeval {
time_t tv_sec; /* 秒 */
suseconds_t tv_usec; /* 毫秒 */
};
2)用户空间的timespec:
struct timespec {
time_t tv_sec; /* 秒 */
long tv_nsec; /* 纳秒 */
};
jiffies:可以实现计时等功能。可以知道当前内核"滴答"次数.
成员函数:#include<1inux/jiffies.h>
初始化:
功能函数;
a.jiffies计数器
current_j = jiffies; /*读取当前值*/
stamp_1 = current_j + HZ; /*未来的1秒*/
stamp_half = current_j + HZ/2; /*半秒*/
stamp_n = current_j + n*HZ/1000;/*n毫秒*/
b.比较时间量,比较节拍计数; a 宏名 b? 1:0.
int time_after(unsigned long a,unsigned long b);
int time_before(unsigned long a,unsigned long b);
int time_after_eq(unsigned long_a,unsigned long b);
int time_before_eq(unsigned long a,unsigned long b);
c.jiffies值和timeval、timespec之间转换
unsigned long timespec_to_jiffies(struct timespec *value);
void jiffies_to_timespec(unsigned long jiffie, struct timespec *value);
unsigned long timeval_to_jiffies(struct timeval *value);
void jiffies_to_timeval(unsigned long jiffies,struct timeval *value);
d.获取当前时间
void do_gettimeofday(struct timeval *tv);
struct timespec current_kernel_time(void);
释放资源:
2.延迟:延迟作用:让程序延迟执行
成员函数:#include<1inux/sched.h>
初始化:
功能函数;
a.长延时
set_current_state(TASK_INTERRUPTIBLE);
schedule_timeout(delay);
b.短延时#include <linux/delay.h>
void ndelay(unsigned long nsecs); /*延时纳秒*/
void udelay(unsigned long usecs); /*延时微妙*/
void mdelay(unsigned long msecs);/*延时毫秒*/
c.不使用忙等待的延迟方式
void msleep(unsigned int millisecs);
unsigned long msleep_interruptible(unsigned int millisecs);
释放资源:
典型应用:
while(time_before(jiffies,end_time)){
schedule();
}
3.struct timer_list:内核定时器struct timer_list{
/*…*/
unsigned long expires;
void (*function)(unsigned long);
unsigned long data;
};
内核定时器:产生定时器中断,写中断服务函数。例如实现按键中断。
成员函数:#include <linux/timer.h>
初始化:
a.这2个初始化不怎么好用
void init_timer(struct timer_list *timer);
struct timer_list TIMER_INITIALIZER(_function,_expires,_data);
功能函数;
a.添加,删除定时器到内核资源,执行完后自动移除定时器
void add_timer(struct timer_list *timer);
int del_timer(struct timer_list *timer);
b.其他
int mod_timer(struct timer_list *timer,unsigned long expires);
int del_timer_sync(struct timer_list *timer);
int timer_pending(const struct timer_list *timer);