Linux 驱动之内核定时器

1、定时器

之前说过两类跟时间相关的内核结构。

1、延时:通过忙等待或者睡眠机制实现延时。

2tasklet和工作队列,通过某种机制使工作推后执行,但不知道执行的具体时间。

接下来要介绍的定时器,能够使工作在指定的时间点上执行,而且不需要使用忙等待这类的延时方法。通过定义一个定时器,告之内核在哪个时间需要执行什么函数就可以了,等时间一到,内核会就执行指定的函数。

2、使用定时器

定时器的使用很简单,只需要三部:

1、定义定时器结构体timer_list

2、设置超时时间,定义定时器处理函数和传参。

3、激活定时器


代码

#include <linux/module.h>
#include <linux/init.h>

#include <linux/sched.h>
#include <linux/timer.h>

#if 0  //定义并初始化定时器结构体timer_list。
/*include/linux/timer.h*/
struct timer_list {
	struct list_head entry;
	unsigned long expires; //设置在执行定时器处理函数的时间

	void (*function)(unsigned long); //定时器处理函数
	unsigned long data; //处理函数的传参

	struct tvec_base *base;
	
	#ifdef CONFIG_TIMER_STATS
		void *start_site;
		char start_comm[16];
		int start_pid;
	#endif
	
};
#endif

struct timer_list my_timer; //1.定义定时器结构体timer_list

void timer_func(unsigned long data) //2.定义定时器处理函数
{
	printk("time out![%d] [%s]\n", (int)data, current->comm); //打印当前进程
}

static int __init test_init(void) //模块初始化函数
{
	 init_timer(&my_timer); //1.初始化timer_list结构

	 my_timer.expires = jiffies + 5*HZ; //2.设定定时器处理函数触发时间为5秒
	 my_timer.function = timer_func; //2.给结构体指定定时器处理函数
	 my_timer.data = (unsigned long)99; //2.设定定时器处理函数的传参

	 add_timer(&my_timer); //3.激活定时器
	 printk("hello timer,current->comm[%s]\n", current->comm);
	 return 0;
 }

static void __exit test_exit(void) //模块卸载函数
{
	printk("good bye timer\n");
}

三、定时器的删除和修改


上面说了,激活定时器后只能执行一遍,如果要实现隔指定时间又重复执行,那就要修改一下代码。

在定时器处理函数中加上两条代码:

my_timer.expires = jiffies + 2*HZ; //重新设定时间,在两秒后再执行

add_timer(&my_timer); //再次激活定时器

这样的话,每个2秒就会再次执行定时器处理函数。

这两条代码也相当与一下的函数:


 mod_timer(&my_timer, jiffies + 2*HZ);


/*kernel/timer.c*/

int mod_timer(struct timer_list *timer, unsigned long expires)

这是改变定时器超时时间的函数,如果在指定的定时器(timer)没超时前调用,超时时间会更新为新的新的超时时间(expires)。如果在定时器超时后调用,那就相当于重新指定超时时间并再次激活定时器。


如果想在定时器没有超时前取消定时器,可以调用以下函数:

/*kernel/timer.c*/

 int del_timer(struct timer_list *timer)

该函数用来删除还没超时的定时器。



你可能感兴趣的:(linux驱动)