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
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.内核定时器示例
内核定时器使用步骤:
- 初始化内核定时器init_timer,设置超时时间,编写内核定时工作函数;
- 启动定时器add_timer;
- 若需要重复定时,则需要在定时器工作函数中修改超时时间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");
审核编辑:汤梓红
-
内核
+关注
关注
3文章
1359浏览量
40179 -
Linux
+关注
关注
87文章
11196浏览量
208662 -
定时器
+关注
关注
23文章
3229浏览量
114291
发布评论请先 登录
相关推荐
评论