我是靠谱客的博主 醉熏路灯,最近开发中收集的这篇文章主要介绍Linux内核定时器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。
在这里插入图片描述

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 <linux/jiffies.h>
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 <linux/kernel.h>
#include <linux/module.h>
#include <asm/io.h>
#include <linux/timer.h>
#include <linux/suspend.h>
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内核定时器Linux内核定时器的全部内容,希望文章能够帮你解决Linux内核定时器Linux内核定时器所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(47)

评论列表共有 0 条评论

立即
投稿
返回
顶部