我是靠谱客的博主 害怕鞋子,这篇文章主要介绍linux内核模块编程(二)----timer定时器,现在分享给大家,希望可以做个参考。

先给自己打个广告,本人的微信公众号正式上线了,搜索:张笑生的地盘,主要关注嵌入式软件开发,足球等等,希望大家多多关注,有问题可以直接留言给我,一定尽心尽力回答大家的问题
在这里插入图片描述

一 why

一般地,在我们嵌入式软件开发中,使用定时器的目的是为了实现周期性地执行某项工作;同样地,linux内核也实现了一种定时器,用于实现内核周期性执行某项工作。

二 what

linux内核实现的这种定时器,称之为动态定时器,是内核用来控制在未来某个时间点(基于jiffies)调度执行某个函数的一种机制,它的实现位于Linux/timer.h 和 kernel/timer.c 文件中。
被调度的函数是异步执行的,类似于一种“软件中断”,处于非进程的上下文中,所以这个被调度函数应该遵循如下规则

复制代码
1
2
3
4
5
1. 没有 current 指针,不允许访问用户空间。因为没有进程上下文,相关代码和被中断的进程没有任何联系。 2. 不能执行休眠(或可能引起休眠的函数)和调度。 3. 任何被访问的数据结构都应该针对并发访问进行保护,以防止竞争条件。 4. 被调度函数运行过一次后就不会再被运行了(相当于自动注销),但可以通过在被调度的函数中重新调度自己来周期运行。

2.1 内核定时器的数据结构

复制代码
1
2
3
4
5
6
7
8
9
struct timer_list { struct list_head entry; // 当一个定时器被注册到内核之后,entry 字段用来连接该定时器到一个内核链表中 unsigned long expires; // 表示期望定时器执行的 jiffies 值,到达该 jiffies 值时,将调用 function 函数 void (*function)(unsigned long); unsigned long data; struct tvec_base *base; //内核内部实现所用的 /* ... */ };

2.2 初始化
由于linux内核版本的不同,关于初始化部分的实现有不同的函数,低版本的用init_timer,高版本是timer_setup

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
#if LINUX_VERSION_CODE < KERNEL_VERSION(4,14,0) init_timer(&dev->getIntrTimer); dev->getIntrTimer.data = (unsigned long) dev; dev->getIntrTimer.function = GetIntrTimerCallback; /* ... */ add_timer(&dev->getIntrTimer); #else timer_setup(&dev->getIntrTimer, GetIntrTimerCallback, 0); /* the third argument may include TIMER_* flags */ /* ... */ #endif

比如当前我的linux版本是4.15,所以在我的实验中,使用的就是timer_setup
2.3 注册
初始化定时器成功之后,我们需要注册该定时器,函数为

复制代码
1
2
add_timer

2.4 修改
定时运行过程中的定时器周期修改函数为

复制代码
1
2
mod_timer

前面我们知道,当定时周期来到时,会执行被调函数,如果我们此时不修改定时器到期时间,则接下来就不会在执行被调函数了,我们可以在被调函数中修改定时器到期时间,实现周期性执行被调函数。

三 how

定时器内核编程示例

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
#include <linux/module.h> #include <linux/kernel.h> #include <linux/timer.h> #include <linux/jiffies.h> static struct timer_list test_timer; static void irq_test_timer_function(struct timer_list *timer) { printk("22 again in irq_test_timer_functionn"); mod_timer(&test_timer, jiffies + 2 * HZ); } static int timer_drv_init(void) { test_timer.expires = jiffies + 2 * HZ; timer_setup(&test_timer, irq_test_timer_function, 0); add_timer(&test_timer); printk(KERN_INFO "already init and add timern"); return 0; } static void timer_drv_exit(void) { printk(KERN_INFO "exit timer drvn"); del_timer(&test_timer); } module_init(timer_drv_init); module_exit(timer_drv_exit); MODULE_LICENSE("GPL");

Makefile文件

复制代码
1
2
3
4
5
6
7
8
9
10
11
obj-m:=test_timer.o KDIR:= /lib/modules/$(shell uname -r)/build PWD:= $(shell pwd) all: $(MAKE) -C $(KDIR) M=$(PWD) modules clean: $(MAKE) -C $(KDIR) M=$(PWD) clean

四 test

复制代码
1
2
3
4
5
6
1. 上传到Ubuntu系统 2. 编译 make 3. 加载 sudo insmod test_timer.ko 4. 查看运行情况 dmesg | tail 5. 卸载 sudo rmmod test_timer

加载时打印
在这里插入图片描述
卸载时打印
在这里插入图片描述

最后

以上就是害怕鞋子最近收集整理的关于linux内核模块编程(二)----timer定时器的全部内容,更多相关linux内核模块编程(二)----timer定时器内容请搜索靠谱客的其他文章。

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

评论列表共有 0 条评论

立即
投稿
返回
顶部