Linux内核定时器

描述

Linux内核定时器

      在Linux内核中,也可以通过定时器来完成定时功能。但和单片机不同的是,Linux内核定时器是一种基于未来时间点的计时方式,它以当前时刻为启动的时间点,以未来的某一时刻为终止点,类似于我们的闹钟。
      当内核定时器定时时间到达时,会进入用户指定的函数,相当于软中断。内核定时器完成注册启动后,仅执行一次后就不会重复执行(即超时候会自动关闭),若需要重复执行则需要手动再次启动(即修改超时时间)。
      Linux内核定时器相关函数位置:include/linux/timer.h

1.相关结构体

  在使用内核定时器时,我们需要关心的相关结构体及其成员:

struct timer_list {
struct list_head entry;
unsigned long expires; /* 定时器时钟节拍*/
struct tvec_base *base;
void (*function)(unsigned long); /*定时器工作函数 */
unsigned long data; /*传给定时器工作函数的参数 */
};

  在Linux内核中,有一个全局变量jiffies用来记录时钟节拍,每当时钟中断触发一次,jiffies就会+1。因此jiffies变量记录了系统从启动开始时钟中断触发的次数。我们由此可以利用jiffies来计算驱动程序运行时长。jiffies每秒增加HZ次,因此jiffies+1的时长有HZ决定。当HZ=100时,jiffies+1的时长则为10ms。在Linux3.5的内核中HZ值默认为200,即jiffies+1的时长则为5ms。
 

Linux

2.相关函数

2.1 定时器初始化init_timer()

#define init_timer(timer)
函数功能: 初始化定时
形参: 定时器结构体

2.2 启动定时器add_timer()

void add_timer(struct timer_list *timer)
函数功能: 启动定时器
形参: 定时器结构体

2.3 修改定时时间mod_timer()

int mod_timer(struct timer_list *timer, unsigned long expires)
函数功能: 修改定时器时间
形参: timer – 定时器结构体
   expires --定时时间( 以时钟节拍填入)

  注意:expires 填写是基于jiffies+延时时间

2.4毫秒转为时钟节拍 msecs_to_jiffies()

unsigned long msecs_to_jiffies(const unsigned int m)
函数功能: 将毫秒时间转换为时钟节拍数
形参: m – 毫秒时间
返回值: – 返回节拍数

2.5微秒转为时钟节拍 usecs_to_jiffies()

unsigned long usecs_to_jiffies(const unsigned int u)
函数功能: 将微秒时间转换为时钟节拍数
形参: m – 位秒时间
返回值: – 返回节拍数

2.6关闭定时器

int del_timer(struct timer_list *timer)
函数功能:关闭定时器(停用一个定时器)
 define del_timer_sync(t)
函数功能:关闭定时器(停用一个定时器),多处理器使用。如果编内核时不支持 SMP(多处理器), del_timer_sync()和 del_timer()等价

2.7 获取jiffies时间

#include 
u64 get_jiffies_64(void)
函数功能: 获取jiffies时间
返回值: 返回时钟节拍jiffies

2.8 获取内核高精度时间

ktime_t ktime_get(void)
函数功能: 获取内核高精度时间
返回值: ktime_t – 共用体类型
union ktime {
	s64	tv64;
	#if BITS_PER_LONG != 64 && !defined(CONFIG_KTIME_SCALAR)
		struct
		 {
			# ifdef __BIG_ENDIAN
			s32	sec, nsec;
			# else
			s32	nsec, sec;
			# endif
		} tv;
	#endif
};

2.9 时间转换函数

s64 ktime_to_ms(const ktime_t kt) /* 将获取的系统时钟转换为ms单位*/
s64 ktime_to_us(const ktime_t kt) /* 将获取的系统时钟转换为us单位*/
/将获取的时间转换为时钟结构体/
struct timeval ktime_to_timeval(const ktime_t kt)
struct timespec ktime_to_timespec(const ktime_t kt)

3.内核定时器示例

  内核定时器使用步骤:

  1. 初始化内核定时器init_timer,设置超时时间,编写内核定时工作函数;
  2. 启动定时器add_timer;
  3. 若需要重复定时,则需要在定时器工作函数中修改超时时间mod_timer
#include 
#include 
#include 
#include 
#include 
struct timer_list timer;
/*定时器工作函数*/
void timer_work(unsigned long data)
{
	ktime_t time1;
	printk("定时器时间到!data=%ld,",data);
	time1=ktime_get();
	printk("定时时间:%llu \n",ktime_to_ms(time1));
	mod_timer(&timer,jiffies+msecs_to_jiffies(2000));/*修改定时时间*/
}
static int __init wbyq_timer_init(void)
{
	timer.expires=jiffies+msecs_to_jiffies(1000);/*定时时间*/
	timer.function=timer_work;/*定时器工作函数*/
	timer.data=666;/*传给定时器工作函数参数,选填*/
	init_timer(&timer);/*初始化定时器*/
	add_timer(&timer);/*启动定时器*/
	return 0;
	
}
/*驱动释放*/
static void __exit wbyq_timer_cleanup(void)
{
	del_timer_sync(&timer);//关闭定时器
    printk("驱动出口,驱动注销成功\n");
}
module_init(wbyq_timer_init);//驱动入口函数
module_exit(wbyq_timer_cleanup);//驱动出口函数

MODULE_LICENSE("GPL");//驱动注册协议
MODULE_AUTHOR("it_ashui");
MODULE_DESCRIPTION("Exynos4 timer Driver");
Linux  

审核编辑:汤梓红
 

 

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分