1. 在linux内核中,timer_list结构体对应一个定时器,2.6.35内核中,定义incude/linux/timer.h
- struct timer_list {
-
13 /*
-
14 * All fields that change during normal runtime grouped to the
-
15 * same cacheline
-
16 */
- 17 struct list_head entry;
-
18 unsigned long expires;//定时器到期时间
-
19 struct
- 20
-
21 void (*function)(unsigned long);
-
22 unsigned long data; 作为参数传入functiong 函数中
-
23
-
24 int slack;
-
25
-
26#ifdef CONFIG_TIMER_STATS
-
27 void *start_site;
-
28 char start_comm[16];
-
29 int start_pid;
-
30#endif
-
31#ifdef CONFIG_LOCKDEP
-
32 struct lockdep_map lockdep_map;
-
33#endif
- 34};
- //定时器列表 一个双列表include/linux/list.h
- struct list_head { struct list_head *next, *prev;};
- 75struct tvec_base {
-
76 spinlock_t lock;
-
77 struct timer_list *running_timer;
-
78 unsigned long timer_jiffies;
-
79 unsigned long next_timer;
-
80 struct tvec_root tv1;
-
81 struct tvec tv2;
-
82 struct tvec tv3;
-
83 struct tvec tv4;
-
84 struct tvec tv5;
- 85} ____cacheline_aligned;
使用timer步骤
1. 定义定时器
struct timer_list my_timer;
2. 初始化定时器
- init_timer(&my_timer);
- my_timer.function=my_timer_func; 该设置设置定时器触发时处理的函数
- my_timer.data=0; 初始化处理函数的参数值,若处理函数没有参数则可简单设置为0或任意其他数值
- my_timer.expires=jiffies+TT; 初始化定时器的到期节拍数
3. 增加定时器
add_timer(struct timer_list *timer)
2.6.35定义/kernel/timer.c
- 849void add_timer(struct timer_list *timer)
-
850{
-
851 BUG_ON(timer_pending(timer));
-
852 mod_timer(timer, timer->expires);
- 853}
4. 删除定时器
del_timer(struct timer_list *timer)
注: del_timer_sync()和del_timer()的同步版,主要在多处理系统中使用,如果编译内核时不支持SMP,del_timer_sync()和del_timer()等价
5.修改定时器的expire
mod_timer(struct time_list *timer,unsigned long expires)
程序一:
my_timer定时器每个1s 打印1 和 second_timer定时器每隔2s打印2.附件:
timer1.rar 将.rar修改为.tar.bz2后解压
内核定时器并不是周期运行,它在超时后自动销毁。因此,如果要实现周期轮询,就需要在定时器执行函数返回前再次激活定时器。add_timer()重新激活
jiffies是Linux内核中的一个全局变量,用来记录自系统启动以来产生的节拍的总数。启动时,内核将该变量初始化为0,此后,每次时钟中断处理程序都会增加该变量的值。
#define HZ 1000
2.6内核的时钟中断频率是1000,也就是说,在1秒里jiffies会被增加1000。因此jiffies + 2 * HZ表示推后2秒钟。有时,需要更改已经激活的定时器,采用如下函数:
mod_timer(&my_timer, jiffies + new_delay);
如果需要在定时器超时前停止定时器,可以使用del_timer()函数:
在多处理器的情况下使用:
del_timer_sync(&polling_timer);
del_timer_sync(&polling_timer);
- #include <linux/init.h>
-
#include <linux/module.h>
-
#include <linux/kernel.h>
-
-
#include <linux/time.h>
-
#include <linux/timer.h>
-
-
#define TT HZ/1
-
-
struct timer_list my_timer; //设备要使用的定时器
-
struct timer_list second_timer;
-
-
static void my_timer_func(unsigned long p)//定时器处理函数
-
{
-
printk("%d\n",1);
-
my_timer.expires=jiffies+TT;
- //内核定时器并不是周期运行,它在超时后自动销毁
-
add_timer(&my_timer);
-
}
-
-
static void second_timer_func(unsigned long p)
-
{
-
printk("%d\n",2);
-
second_timer.expires=jiffies+2*TT;
-
add_timer(&second_timer);
-
}
-
static int __init my_timer_init(void)
-
{
-
init_timer(&my_timer);
-
my_timer.function=my_timer_func;
-
my_timer.data=0;
-
my_timer.expires=jiffies+TT;
-
add_timer(&my_timer);
-
-
init_timer(&second_timer);
-
second_timer.function=second_timer_func;
-
second_timer.data=0;
-
second_timer.expires=jiffies+2*TT;
-
add_timer(&second_timer);
-
-
printk("welcom\n");
-
return 0;
-
}
-
-
static void __exit my_timer_exit(void)
-
{
-
del_timer(&my_timer);
-
del_timer(&second_timer);
-
printk("bye\n");
-
}
-
-
module_init(my_timer_init);
-
module_exit(my_timer_exit);
-
-
MODULE_LICENSE("Dual BSD/GPL");
- MODULE_AUTHOR("yuweixian4230.blog.chinaunx.net");
Makefile
- obj-m:=timer.o
-
KERNELDIR := /lib/modules/2.6.35-31-generic/build
-
PWD :=$(shell pwd)
-
-
modules:
-
$(MAKE) -C $(KERNELDIR) M=$(PWD) modules
-
-
modules_install:
-
$(MAKE) -C $(KERNELDIR) M=$(PWD) modules_install
-
-
clean:
- rm -rf *.o *.ko *.mod.c *.order *.symvers
dmesg | tail -15 或
cat /var/log/syslog | tail -15
2.程序二
功能:简单延迟当前进程执行的程序,延迟是通过定时器来实现的;
- #include <linux/module.h>
-
#include <linux/init.h>
-
#include <linux/kernel.h>
-
-
#include <linux/sched.h>
-
#include <linux/timer.h>
-
-
struct timer_list my_timer;// defination timer
-
int timeout=10*HZ;
-
-
static void time_handler(unsigned long data)
-
{
- struct task_struct *p=(struct task_struct *)data;//定时器处理函数,执行该函数获取挂起进程的pid,唤醒该进程
-
wake_up_process(p);///唤醒进程
-
printk("current jiffies is %ld\n",jiffies);
-
}
-
-
static int __init timer_init(void)
-
{
-
printk("my module worked\n");
-
init_timer(&my_timer);
-
my_timer.data=(unsigned long )current;////将当前进程的pid作为参数传递
-
my_timer.expires=jiffies+timeout//a
-
my_timer.function=time_handler;
-
add_timer(&my_timer);
-
printk("current jiffies is %ld\n",jiffies);
-
set_current_state(TASK_INTERRUPTIBLE);// 进程睡眠
-
schedule();////挂起该进程 放弃CPU
-
del_timer(&my_timer);
-
return 0;
-
}
-
-
static void __exit timer_exit(void)
-
{
-
printk("unloading my module.\n");
-
}
-
-
module_init(timer_init);
-
module_exit(timer_exit);
-
-
MODULE_AUTHOR("yuweixian4230.blog.chinaunx.net");
- MODULE_LICENSE("GPL");
- ywx@ywx:~/Desktop/module/timer/timer2$ dmesg | tail -5
-
[ 578.542874] bye
-
[13945.374106] my module worked
-
[13945.374176] current jiffies is 3411343
-
[13955.392720] current jiffies is 3413848
-
[13962.993754] unloading my module.
- ywx@ywx:~/Desktop/module/timer/timer2$