9.3时间管理之timer


内核定时器:

涉及头文件:

#include <linux/timer.h>

一个内核定时器对应如下一个结构体变量:

struct timer_list {
struct list_head entry;
unsigned long expires; //定时的未来时间点,以jiffies为参考点。
struct tvec_base *base;

void (*function)(unsigned long); //定时处理函数
unsigned long data; //定时处理函数需要的点心

int slack;

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


a. 定时对象的实例化

<1>
struct timer_list timer;
init_timer(&timer);

timer.function = do_timer_hehe;
timer.expires = jiffies + n*HZ;
timer.data = (unsigned long)&val;

<2>

struct timer_list timer;

setup_timer(&timer, do_timer_hehe, (unsigned long)&val);
timer.expires = jiffies + n*HZ;

<3>
DEFINE_TIMER(timer, do_timer_hehe, jiffies+n*HZ, (unsigned long)&val);

b. 定时器的注册及启动

add_timer(&timer);

c. 当希望周期性产生定时的时候,需要在定时处理函数中调用如下函数再次启动下一次
的定时:

mod_timer(&timer, jiffies + n*HZ);

d. 在驱动模块的出口移除曾经注册的定时器

del_timer(&timer);
del_timer_sync(&timer);

 

timer目录:

1 obj-m    := demo.o
2 
3 KERNEL    := /linux-3.5/
4 
5 all:
6     make -C $(KERNEL) M=`pwd`
7 clean:
8     make -C $(KERNEL) M=`pwd` clean
9     

 

  1 #ifndef _LINUX_TIMER_H
  2 #define _LINUX_TIMER_H
  3 
  4 #include <linux/list.h>
  5 #include <linux/ktime.h>
  6 #include <linux/stddef.h>
  7 #include <linux/debugobjects.h>
  8 #include <linux/stringify.h>
  9 
 10 struct tvec_base;
 11 
 12 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 tvec_base *base;
 20 
 21     void (*function)(unsigned long);
 22     unsigned long data;
 23 
 24     int slack;
 25 
 26 #ifdef CONFIG_TIMER_STATS
 27     int start_pid;
 28     void *start_site;
 29     char start_comm[16];
 30 #endif
 31 #ifdef CONFIG_LOCKDEP
 32     struct lockdep_map lockdep_map;
 33 #endif
 34 };
 35 
 36 extern struct tvec_base boot_tvec_bases;
 37 
 38 #ifdef CONFIG_LOCKDEP
 39 /*
 40  * NB: because we have to copy the lockdep_map, setting the lockdep_map key
 41  * (second argument) here is required, otherwise it could be initialised to
 42  * the copy of the lockdep_map later! We use the pointer to and the string
 43  * "<file>:<line>" as the key resp. the name of the lockdep_map.
 44  */
 45 #define __TIMER_LOCKDEP_MAP_INITIALIZER(_kn)                \
 46     .lockdep_map = STATIC_LOCKDEP_MAP_INIT(_kn, &_kn),
 47 #else
 48 #define __TIMER_LOCKDEP_MAP_INITIALIZER(_kn)
 49 #endif
 50 
 51 /*
 52  * Note that all tvec_bases are 2 byte aligned and lower bit of
 53  * base in timer_list is guaranteed to be zero. Use the LSB to
 54  * indicate whether the timer is deferrable.
 55  *
 56  * A deferrable timer will work normally when the system is busy, but
 57  * will not cause a CPU to come out of idle just to service it; instead,
 58  * the timer will be serviced when the CPU eventually wakes up with a
 59  * subsequent non-deferrable timer.
 60  */
 61 #define TBASE_DEFERRABLE_FLAG        (0x1)
 62 
 63 #define TIMER_INITIALIZER(_function, _expires, _data) {        \
 64         .entry = { .prev = TIMER_ENTRY_STATIC },    \
 65         .function = (_function),            \
 66         .expires = (_expires),                \
 67         .data = (_data),                \
 68         .base = &boot_tvec_bases,            \
 69         .slack = -1,                    \
 70         __TIMER_LOCKDEP_MAP_INITIALIZER(        \
 71             __FILE__ ":" __stringify(__LINE__))    \
 72     }
 73 
 74 #define TBASE_MAKE_DEFERRED(ptr) ((struct tvec_base *)        \
 75           ((unsigned char *)(ptr) + TBASE_DEFERRABLE_FLAG))
 76 
 77 #define TIMER_DEFERRED_INITIALIZER(_function, _expires, _data) {\
 78         .entry = { .prev = TIMER_ENTRY_STATIC },    \
 79         .function = (_function),            \
 80         .expires = (_expires),                \
 81         .data = (_data),                \
 82         .base = TBASE_MAKE_DEFERRED(&boot_tvec_bases),    \
 83         __TIMER_LOCKDEP_MAP_INITIALIZER(        \
 84             __FILE__ ":" __stringify(__LINE__))    \
 85     }
 86 
 87 #define DEFINE_TIMER(_name, _function, _expires, _data)        \
 88     struct timer_list _name =                \
 89         TIMER_INITIALIZER(_function, _expires, _data)
 90 
 91 void init_timer_key(struct timer_list *timer,
 92             const char *name,
 93             struct lock_class_key *key);
 94 void init_timer_deferrable_key(struct timer_list *timer,
 95                    const char *name,
 96                    struct lock_class_key *key);
 97 
 98 #ifdef CONFIG_LOCKDEP
 99 #define init_timer(timer)                        \
100     do {                                \
101         static struct lock_class_key __key;            \
102         init_timer_key((timer), #timer, &__key);        \
103     } while (0)
104 
105 #define init_timer_deferrable(timer)                    \
106     do {                                \
107         static struct lock_class_key __key;            \
108         init_timer_deferrable_key((timer), #timer, &__key);    \
109     } while (0)
110 
111 #define init_timer_on_stack(timer)                    \
112     do {                                \
113         static struct lock_class_key __key;            \
114         init_timer_on_stack_key((timer), #timer, &__key);    \
115     } while (0)
116 
117 #define setup_timer(timer, fn, data)                    \
118     do {                                \
119         static struct lock_class_key __key;            \
120         setup_timer_key((timer), #timer, &__key, (fn), (data));\
121     } while (0)
122 
123 #define setup_timer_on_stack(timer, fn, data)                \
124     do {                                \
125         static struct lock_class_key __key;            \
126         setup_timer_on_stack_key((timer), #timer, &__key,    \
127                      (fn), (data));            \
128     } while (0)
129 #define setup_deferrable_timer_on_stack(timer, fn, data)        \
130     do {                                \
131         static struct lock_class_key __key;            \
132         setup_deferrable_timer_on_stack_key((timer), #timer,    \
133                             &__key, (fn),    \
134                             (data));        \
135     } while (0)
136 #else
137 #define init_timer(timer)\
138     init_timer_key((timer), NULL, NULL)
139 #define init_timer_deferrable(timer)\
140     init_timer_deferrable_key((timer), NULL, NULL)
141 #define init_timer_on_stack(timer)\
142     init_timer_on_stack_key((timer), NULL, NULL)
143 #define setup_timer(timer, fn, data)\
144     setup_timer_key((timer), NULL, NULL, (fn), (data))
145 #define setup_timer_on_stack(timer, fn, data)\
146     setup_timer_on_stack_key((timer), NULL, NULL, (fn), (data))
147 #define setup_deferrable_timer_on_stack(timer, fn, data)\
148     setup_deferrable_timer_on_stack_key((timer), NULL, NULL, (fn), (data))
149 #endif
150 
151 #ifdef CONFIG_DEBUG_OBJECTS_TIMERS
152 extern void init_timer_on_stack_key(struct timer_list *timer,
153                     const char *name,
154                     struct lock_class_key *key);
155 extern void destroy_timer_on_stack(struct timer_list *timer);
156 #else
157 static inline void destroy_timer_on_stack(struct timer_list *timer) { }
158 static inline void init_timer_on_stack_key(struct timer_list *timer,
159                        const char *name,
160                        struct lock_class_key *key)
161 {
162     init_timer_key(timer, name, key);
163 }
164 #endif
165 
166 static inline void setup_timer_key(struct timer_list * timer,
167                 const char *name,
168                 struct lock_class_key *key,
169                 void (*function)(unsigned long),
170                 unsigned long data)
171 {
172     timer->function = function;
173     timer->data = data;
174     init_timer_key(timer, name, key);
175 }
176 
177 static inline void setup_timer_on_stack_key(struct timer_list *timer,
178                     const char *name,
179                     struct lock_class_key *key,
180                     void (*function)(unsigned long),
181                     unsigned long data)
182 {
183     timer->function = function;
184     timer->data = data;
185     init_timer_on_stack_key(timer, name, key);
186 }
187 
188 extern void setup_deferrable_timer_on_stack_key(struct timer_list *timer,
189                         const char *name,
190                         struct lock_class_key *key,
191                         void (*function)(unsigned long),
192                         unsigned long data);
193 
194 /**
195  * timer_pending - is a timer pending?
196  * @timer: the timer in question
197  *
198  * timer_pending will tell whether a given timer is currently pending,
199  * or not. Callers must ensure serialization wrt. other operations done
200  * to this timer, eg. interrupt contexts, or other CPUs on SMP.
201  *
202  * return value: 1 if the timer is pending, 0 if not.
203  */
204 static inline int timer_pending(const struct timer_list * timer)
205 {
206     return timer->entry.next != NULL;
207 }
208 
209 extern void add_timer_on(struct timer_list *timer, int cpu);
210 extern int del_timer(struct timer_list * timer);
211 extern int mod_timer(struct timer_list *timer, unsigned long expires);
212 extern int mod_timer_pending(struct timer_list *timer, unsigned long expires);
213 extern int mod_timer_pinned(struct timer_list *timer, unsigned long expires);
214 
215 extern void set_timer_slack(struct timer_list *time, int slack_hz);
216 
217 #define TIMER_NOT_PINNED    0
218 #define TIMER_PINNED        1
219 /*
220  * The jiffies value which is added to now, when there is no timer
221  * in the timer wheel:
222  */
223 #define NEXT_TIMER_MAX_DELTA    ((1UL << 30) - 1)
224 
225 /*
226  * Return when the next timer-wheel timeout occurs (in absolute jiffies),
227  * locks the timer base and does the comparison against the given
228  * jiffie.
229  */
230 extern unsigned long get_next_timer_interrupt(unsigned long now);
231 
232 /*
233  * Timer-statistics info:
234  */
235 #ifdef CONFIG_TIMER_STATS
236 
237 extern int timer_stats_active;
238 
239 #define TIMER_STATS_FLAG_DEFERRABLE    0x1
240 
241 extern void init_timer_stats(void);
242 
243 extern void timer_stats_update_stats(void *timer, pid_t pid, void *startf,
244                      void *timerf, char *comm,
245                      unsigned int timer_flag);
246 
247 extern void __timer_stats_timer_set_start_info(struct timer_list *timer,
248                            void *addr);
249 
250 static inline void timer_stats_timer_set_start_info(struct timer_list *timer)
251 {
252     if (likely(!timer_stats_active))
253         return;
254     __timer_stats_timer_set_start_info(timer, __builtin_return_address(0));
255 }
256 
257 static inline void timer_stats_timer_clear_start_info(struct timer_list *timer)
258 {
259     timer->start_site = NULL;
260 }
261 #else
262 static inline void init_timer_stats(void)
263 {
264 }
265 
266 static inline void timer_stats_timer_set_start_info(struct timer_list *timer)
267 {
268 }
269 
270 static inline void timer_stats_timer_clear_start_info(struct timer_list *timer)
271 {
272 }
273 #endif
274 
275 extern void add_timer(struct timer_list *timer);
276 
277 extern int try_to_del_timer_sync(struct timer_list *timer);
278 
279 #ifdef CONFIG_SMP
280   extern int del_timer_sync(struct timer_list *timer);
281 #else
282 # define del_timer_sync(t)        del_timer(t)
283 #endif
284 
285 #define del_singleshot_timer_sync(t) del_timer_sync(t)
286 
287 extern void init_timers(void);
288 extern void run_local_timers(void);
289 struct hrtimer;
290 extern enum hrtimer_restart it_real_fn(struct hrtimer *);
291 
292 unsigned long __round_jiffies(unsigned long j, int cpu);
293 unsigned long __round_jiffies_relative(unsigned long j, int cpu);
294 unsigned long round_jiffies(unsigned long j);
295 unsigned long round_jiffies_relative(unsigned long j);
296 
297 unsigned long __round_jiffies_up(unsigned long j, int cpu);
298 unsigned long __round_jiffies_up_relative(unsigned long j, int cpu);
299 unsigned long round_jiffies_up(unsigned long j);
300 unsigned long round_jiffies_up_relative(unsigned long j);
301 
302 #endif

 

 1 /* head file */
 2 #include <linux/init.h>
 3 #include <linux/module.h>
 4 #include <linux/sched.h>
 5 
 6 #include <linux/timer.h>
 7 
 8 #include <linux/delay.h>
 9 
10 #define PERIORD 2
11 
12 static struct  timer_list timer;//1.定义一个定时对象
13 
14 static void do_timer_hehe (unsigned long data)//定时处理函数/data接收的就是定时处理函数需要的参数(点心)
15 {
16     printk("In %s: %s\n", __func__, (char *)data);
17 
18     mod_timer(&timer, jiffies+HZ*PERIORD);//3.周期性产生定时
19 }
20 
21 /* driver module entry */
22 static int __init demo_init(void)
23 {
24     setup_timer(&timer, do_timer_hehe, (unsigned long)"hehe");//1.定时对象的实例化/第三个参数为定时处理函数要传递的参数(准备的点心)
25     timer.expires = PERIORD*HZ + jiffies;//1.以jiffies为参考点,定时的未来时间点
26 
27     add_timer(&timer);//2.定时器的注册及启动
28  
29     return 0;
30 }
31 
32 module_init(demo_init);
33 
34 
35 /* driver module exit */
36 static void __exit demo_exit(void)
37 {
38     del_timer_sync(&timer);//4.在驱动模块出口移除曾经注册的定时器。
39 }
40 module_exit(demo_exit);
41 
42 /* driver module description */
43 MODULE_LICENSE("GPL");
44 
45 MODULE_AUTHOR("crmn");
46 MODULE_VERSION("crmn1.0");
47 MODULE_DESCRIPTION("example for driver module arch");

posted @ 2017-04-06 11:47  bkycrmn  阅读(1398)  评论(1)    收藏  举报