您的位置:首页 > 运维架构 > Linux

Linux 定时器(内核态)

2015-11-24 17:58 501 查看
本文参考文档

头文件以及简单使用流程

头文件:
#include <linux/timer.h>

简单使用流程:

struct timer_list test_timer;

setup_timer(&test_timer, timer_print, 1234);

test_timer.expires = jiffies + 5 * HZ;

add_timer(&test_timer);

说明

1. 定义定时器 test_timer

值得注意的是,定义定时器时注意定时器为全局变量或者是通过kmalloc从堆中申请到的内存。否则定时器会在函数生命周期结束后被销毁,导致出现错误。


2. setup_timer初始化test_timer

首先来看一下setup_timer的源代码

#define setup_timer(timer, fn, data)                    \
__setup_timer((timer), (fn), (data), 0)

#define __setup_timer(_timer, _fn, _data, _flags)           \
do {
4000
\
__init_timer((_timer), (_flags));           \
(_timer)->function = (_fn);             \
(_timer)->data = (_data);               \
} while (0)


很容易可以看出,这个函数只是简单的往test_timer这个数据结构中填充一些内容。其实在add_timer这个函数执行之前,test_timer结构里的数据都可以随意更改。其中1234是随手写的一个数据,将会作为参数传入触发器的function中(在这里是timer_print)。其实这个data参数可以通过强转传入指针,例如:

(unsigned long)&test_timer;


3. 设定时间

test_timer.expires = jiffies + 5 * HZ;


在这句代码中expires成员是定时器,设定了触发函数的时间。HZ代表的是系统每一秒的滴答时钟计算数,可以从config中查到(shell命令,本人内核是3.7.10)。

#cat /boot/config-3.7.10 |grep CONFIG_HZ


其中jiffies是LINUX中定义的一个全局变量,记录的是从系统启动到当前使用的时间。假如要计算系统已经运行的时间,可以简单通过以下计算获得:

jiffies / HZ


这一句的意思是将定时器设置为5秒后触发(由于程序运行本身需要消耗一些时间,因此并不是绝对精确的。假如在这句语句定义后调用msleep(1000)睡眠3秒,那么可能定时器就会在add_timer之后,只剩下不足4秒的时间了)。

4. 添加定时器
add_timer(&test_timer);

Linux内核中定时器的实现涉及到一个双向链表,这个链表中的每一个节点都是

struct timer_list


类型。初始化的的简单调用过程,从kernel/init/main.c到kernel/kernel/timer.c

start_kernel()->init_timers()


更深一层的内容原理请查看参考文档

代码

源代码 test_timer.c

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

struct timer_list test_timer;

/*static DEFINE_TIMER(test_timer, test_print, 0, 0)*/
void timer_print(unsigned long data)
{
printk(KERN_INFO "timer_printk %ld\n", data);
return;
}

static int __init test_init(void)
{
printk(KERN_INFO "test_timer\n");
setup_timer(&test_timer, timer_print, 900);
test_timer.expires = jiffies + 5*HZ;
add_timer(&test_timer);
return 0;
}

static void test_exit(void)
{
printk(KERN_INFO "test_exit\n");
del_timer(&test_timer);
return;
}

module_init(test_init);
module_exit(test_exit);
MODULE_LICENSE("GPL");


Makefile

ccflags-y += -O0 -g
obj-m := test_timer.o
KDIR :=/lib/modules/$(shell uname -r)/build
PWD :=$(shell pwd)

default:
$(MAKE) -C $(KDIR) SUBDIRS=$(PWD) modules
clean:
$(MAKE) -C $(KDIR) SUBDIRS=$(PWD) clean
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  内核 linux 定时器