博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
全志A33开发板Linux内核定时器编程
阅读量:6623 次
发布时间:2019-06-25

本文共 3010 字,大约阅读时间需要 10 分钟。

开发平台

*  芯灵思SinlinxA33开发板

淘宝店铺:

image

嵌入式linux 开发板交流 641395230

Linux 内核定时器是内核用来控制在未来某个时间点(基于jiffies)调度执行某个函数的一种机制,其实现位于 和 kernel/timer.c 文件中。

内核定时器的数据结构

struct timer_list {    struct list_head entry;  //双向链表元素list:用来将多个定时器连接成一条双向循环队列。    unsigned long expires; //expires 字段表示期望定时器执行的 jiffies 值,到达该 jiffies 值时,将调用 function 函数,并传递 data 作为参数。    void (*function)(unsigned long); //指向一个可执行函数。当定时器到期时,内核就执行function所指定的函数。而data域则被内核用作function函数的调用参数。    unsigned long data;     struct tvec_base *base;    /* ... */}

时间比较操作

在定时器应用中经常需要比较两个时间值,以确定timer是否超时,所以Linux内核在timer.h头文件中定义了4个时间关系比较操作宏。这里我们说时刻a在时刻b之后,就意味着时间值a≥b。Linux强烈推荐用户使用它所定义的下列4个时间比较操作宏(include/linux/timer.h):

#define time_after(a,b) ((long)(b) - (long)(a) < 0) #define time_before(a,b) time_after(b,a) #define time_after_eq(a,b) ((long)(a) - (long)(b) >= 0) #define time_before_eq(a,b) time_after_eq(b,a)

Linux 内核时间相关转换函数

1. unsigned long usecs_to_jiffies(const unsigned int u)

功能: 把微秒转换成时钟节拍

参数: u 时间微秒
返回: 对应的时钟节拍数量

2. unsigned long msecs_to_jiffies(const unsigned int m)

功能: 把毫秒转换成时钟节拍

参数: u 时间毫秒
返回: 对应的时钟节拍数量
示例: 要定时从现在开始, 3 毫秒执行一个函数
expires 设置为 jiffies+ msecs_to_jiffies(3)

Linux 内核定时器操作相关 API

  1. 静态定义结构体变量并且初始化(宏)
    DEFINE_TIMER(_name, _function, _expires, _data)

功能: 定义一个名字为_name 的 struct timer_list 结构的变量, 并且初始化它的 function, expires, data 成员

  1. 定时器初始化(宏)
    init_timer(timer)

功能: 只是对 struct timer_list 结构成员进行一些基础初始化操作, function, expires, data 成员还需要用户自

己填充。

3.设置定时器(宏)

setup_timer(timer, fn, data)
功能: 设置定时器中的 function, data 和一些基础成员, expires 并没有初始化, 需要用户自己进行初始化

注册定时器到内核

void add_timer(struct timer_list timer)
功能: 向内核注册一个定时器, 注册后会马上开始计时。

从内核注销定时器

int del_timer(struct timer_list timer);
功能: 从内核定时链表上删除指定的定时器, 删除后就不会再执行绑定的函数

修改定时器定时时间值, 并且重新注册

int mod_timer(struct timer_list timer, unsigned long expire0.s);
功能: 修改定时器定时时间值, 并且重新注册, 不管这个定时的超时函数是否执行过。 执行完成后会马上启
动定时。

内核定时器编程步骤

Step1 定义timer_list 结构变量Step2 定义超时函数Step3 对timer_list结构变量进行初始化Step4 注册定时器,启动定时Step5 注销定时器

实验平台:芯灵思SinlinxA33开发板

驱动代码:

#include 
#include
#include
//Step1 timer_list 结构变量struct timer_list timer;//Step2 超时函数void timer_fun(long data){ printk("%s is call! data:%d\r\n",__FUNCTION__,data);//__FUNCTION__ 获取当前函数名 mod_timer(&timer, jiffies + HZ*1); //再次修改本定时器超时时间为当前时间后1秒}static int __init timer_init(void){ //Step3 对timer_list结构变量进行初始 init_timer(&timer); setup_timer(&timer, timer_fun, 666); timer.expires = jiffies + HZ*2; //Step4 注册定时器,启动定时 add_timer(&timer); printk("Timer start!\r\n"); return 0;}static void __exit timer_exit(void) //Module exit function specified by module_exit(){ //Step5 注销定时器 del_timer_sync(&timer); printk("Timer over!\r\n");}module_init(timer_init);module_exit(timer_exit);MODULE_LICENSE("GPL");

Makefile代码:

KERN_DIR = /work/lichee/linux-3.4all:        make -C $(KERN_DIR) M=`pwd` modules clean:        make -C $(KERN_DIR) M=`pwd` modules clean        rm -rf modules.orderobj-m        += timer_drv.o

最后使用 dmseg 命令查看,可以看到每隔1秒打印一次

转载地址:http://fltpo.baihongyu.com/

你可能感兴趣的文章
MySQL备份账号权限
查看>>
15个重要的Android代码
查看>>
(转)android 牛人必修 ant 编译android工程
查看>>
求最大公约数与最小公倍数
查看>>
C# Winform 跨线程更新UI控件常用方法总结(转)
查看>>
eclipse菜单栏不显示 + the system is running in lou-graphics mode问题
查看>>
【WebService】使用jaxb完成对象和xml的转换
查看>>
如何去除My97 DatePicker控件上右键弹出官网的链接 - 如何debug混淆过的代码
查看>>
多文档
查看>>
输入5个学生的信息(包括学号,姓名,英语成绩,计算机语言成绩和数据库成绩), 统计各学生的总分,然后将学生信息和统计结果存入test.txt文件中...
查看>>
BZOJ2337 [HNOI2011]XOR和路径
查看>>
C# 该行已经属于另一个表 ...
查看>>
android 避免线程的重复创建(HandlerThread、线程池)
查看>>
手游-放开那三国socket协议分析
查看>>
SQL Lazy Spool Eager Spool
查看>>
type的解释
查看>>
Windows Phone 8 开发环境搭建
查看>>
2017:IDC市场规模将持续增长 增速放缓
查看>>
从自动驾驶到学习机器学习:解读2017科技发展的15大趋势
查看>>
SinoBBD探索"一体化"大数据创新发展
查看>>