在将来某个时间点调度执行某个动作,同时在该时间点到达之前不会阻塞当前进程,则可以使用内核定时器。一个内核定时器是一个数据结构,它告诉内核在用户定义的时间点使用用户定义的参数来执行一个用户定义的函数。内核定时器这种异步执行类似于硬件中断发生时的情景,实际上内核定时器常常是作为“软件中断”的结果而运行的。定时器函数以原子的方式运行。内核定时器的另一个重要特性是,任务可以将自己注册在稍后的时间重新运行。还有一个重要特性是,即使在单处理器系统上,定时器也会是竞态的。
基本API:
头文件:<linux/timer.h>
void init_timer(struct timer_list *timer);//旧版内核初始化内核定时器
void timer_setup(timer_list *, callback, (unsigned int) flags);//4.14版本内核之后
void add_timer(struct timer_list *timer);
int del_timer(struct timer_list *timer);
int mod_timer(struct timer_list *timer, unsigned long expires);
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/time.h>
#include <linux/timer.h>
#include <linux/version.h>
typedef struct
{
struct timer_list myTimer;
char data[32];
}TIMER_TEST_S;
static struct timeval lastTime;
static TIMER_TEST_S timerTest = {0};
void timer_callback1(unsigned long arg)
{
char *str = (char *)arg;
struct timeval curTime;
printk("%s: %s\n", __func__, str);
do_gettimeofday(&curTime);
printk("interval: %ld s, %ld us\n",
curTime.tv_sec - lastTime.tv_sec, curTime.tv_usec - lastTime.tv_usec);
lastTime = curTime;
mod_timer(&timerTest.myTimer, jiffies + 1*HZ);
}
void timer_callback2(struct timer_list* t)
{
struct timeval curTime;
TIMER_TEST_S *test = from_timer(test, t, myTimer);
printk("%s: %s\n", __func__, test->data);
do_gettimeofday(&curTime);
printk("interval: %ld s, %ld us\n",
curTime.tv_sec - lastTime.tv_sec, curTime.tv_usec - lastTime.tv_usec);
lastTime = curTime;
mod_timer(&timerTest.myTimer, jiffies + 1*HZ);
}
static int __init hello_init(void)
{
printk("hello_init. \n");
do_gettimeofday(&lastTime);
strcpy(timerTest.data, "hello");
//注册定时器
#if LINUX_VERSION_CODE < KERNEL_VERSION(4,14,0)
init_timer(&timerTest.myTimer);
timerTest.myTimer.function = timer_callback1;
timerTest.myTimer.data = (unsigned long *)timerTest.data;
#else
timer_setup(&timerTest.myTimer, timer_callback2, 0);
#endif
timerTest.myTimer.expires = jiffies + 1*HZ;
add_timer(&timerTest.myTimer);
return 0;
}
static void __exit hello_exit(void)
{
printk("hello_exit. \n");
del_timer(&timerTest.myTimer);
}
MODULE_LICENSE("GPL");
module_init(hello_init);
module_exit(hello_exit);