Linux 内核定时器 二 例子demo
程序员文章站
2022-06-09 13:08:30
...
环境: Ubuntu16
Linux ubuntu 4.15.0-29-generic #31~16.04.1-Ubuntu SMP Wed Jul 18 08:54:04 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux
我在写 demo 的时候,编译的时候遇到几个错误:
打开 Linux 4.15.0-29 内核中的 timer.h 并没有搜索到宏init_timer
Linux 4.15.0-29 和 Linux linux-3.10.y 中的 timer.h 改动蛮大。
Ubuntu18 都出来蛮久了,相信安装新虚拟机的朋友会选择更新 Ubuntu 版本。
我使用的是 Ubuntu16 环境:
下面给出我在写测试demo 时,发现的 timer.h 的差异:
- 初始化函数的接口有所变动;
- struct timer_list // 结构体组员变动
struct timer_list 差异如下图所示
新的内核中删除了
// 删除的成员变量:
unsigned long data;
int slack;
#ifdef CONFIG_TIMER_STATS
int start_pid;
void *start_site;
char start_comm[16];
#endif
初始化函数的接口
旧接口:
- init_timer(timer)
- DEFINE_TIMER(_name, _function, _expires, _data)
- setup_timer(timer, fn, data)
新接口:
-
init_timer(timer) -删除 - DEFINE_TIMER(_name, _function)
- timer_setup(timer, callback, flags)
demo 代码
定时器调用流程:
1. 初始化
a. 宏 init_timer
b. 宏DEFINE_TIMER
c. 宏 setup_timer
2.向内核中添加定时器
a. add_timer - 初始化完成后,向内核中添加定时器
b. mod_timer - 如果需要周期性执行任务,在定时器回调函数中添加 mod_timer
3. 手动/自动释放
a. 定时器运行后,不会再运行,类似自动注销;
b. 定时器未运行,可手动释放 - del_timer
dev_test.c
#include <linux/module.h>
#include <linux/timer.h>
#include <linux/jiffies.h>
void time_pre(struct timer_list *timer);
struct timer_list mytimer;
// DEFINE_TIMER(mytimer, time_pre);
void time_pre(struct timer_list *timer)
{
printk("%s\n", __func__);
mytimer.expires = jiffies + 500 * HZ/1000; // 500ms 运行一次
mod_timer(&mytimer, mytimer.expires); // 2.2 如果需要周期性执行任务,在定时器回调函数中添加 mod_timer
}
// 驱动接口
int __init chr_init(void)
{
timer_setup(&mytimer, time_pre, 0); // 1. 初始化
mytimer.expires = jiffies + 500 * HZ/1000;
add_timer(&mytimer); // 2.1 向内核中添加定时器
printk("init success\n");
return 0;
}
void __exit chr_exit(void)
{
if(timer_pending(&mytimer))
{
del_timer(&mytimer); // 3.释放定时器
}
printk("exit Success \n");
}
module_init(chr_init);
module_exit(chr_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("XXX");
MODULE_DESCRIPTION("a simple char device example");
makefile
# makefile
obj-m := drv_test.o
KERNEL_DIR := /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)
.PHONY:clean
all:
make -C $(KERNEL_DIR) M=$(PWD) modules
clean:
rm -f *.o *.ko *.mod.c *.mod.o *.symvers
运行:
sudo insmod drv_test.ko # 加载驱动
sudo rmmod drv_test # 卸载驱动
dmesg 查看内核打印信息