我们来检查一下这些 API 函数的实际运行情况。清单 1 提供了一个简单的内核模块,用于展示简单计时器 API 的核心特点。在 init_module
中,您使用 setup_timer
初始化了一个计时器,然后调用 mod_timer
来启动它。当计时器过期时,将调用回调函数my_timer_callback
。最后,当您删除模块时,计时器删除(通过 del_timer
)发生。(注意来自 del_timer
的返回检查,它确定计时器是否还在使用。)
清单 1. 探索简单计时器 API
#include <linux/kernel.h> #include <linux/module.h> #include <linux/timer.h> MODULE_LICENSE("GPL"); static struct timer_list my_timer; void my_timer_callback( unsigned long data ) { printk( "my_timer_callback called (%ld).\n", jiffies ); } int init_module( void ) { int ret; printk("Timer module installing\n"); // my_timer.function, my_timer.data setup_timer( &my_timer, my_timer_callback, 0 ); printk( "Starting timer to fire in 200ms (%ld)\n", jiffies ); ret = mod_timer( &my_timer, jiffies + msecs_to_jiffies(200) ); if (ret) printk("Error in mod_timer\n"); return 0; } void cleanup_module( void ) { int ret; ret = del_timer( &my_timer ); if (ret)
printk("Timer module uninstalling\n"); return; } |
您可以在 ./include/linux/timer.h 中进一步了解计时器 API。尽管简单计时器 API 简单有效,但它并不能提供实时应用程序所需的准确性。为此,我们来看一下 Linux 最近新增的功能,该功能用于支持精确度更高的计时器。
一个简单的内核程序,每500ms执行一次func500
helloworld.c
#include <linux/init.h>
#include <linux/module.h>
#include <linux/timer.h>
MODULE_LICENSE("Dual BSD/GPL");
struct timer_list my_timer;
void func500(unsigned long data)
{
static int a=0;
printk("nihao%d\ncurrent time is %ld\n",a,jiffies);
a++;
my_timer.expires=jiffies+msecs_to_jiffies(500);
add_timer(&my_timer);
}
void timer_call(void)
{
init_timer(&my_timer);
my_timer.expires=jiffies+msecs_to_jiffies(500);
my_timer.data=0;
my_timer.function=func500;
add_timer(&my_timer);
}
static int hello_init(void)
{
printk("Hello, World\n");
timer_call();
return 0;
}
static void hello_exit(void)
{
printk("Goodbye ,cruel world\n");
del_timer(&my_timer);
}
module_init(hello_init);
module_exit(hello_exit);
Makefile
obj-m:=helloworld.o
KDIR:=/lib/modules/$(shell uname -r)/build
PWD:=$(shell pwd)
dafault:
$(MAKE) -C $(KDIR) M=$(PWD) modules
clean:
$(MAKE) -C $(KDIR) M=$(PWD) clean
install:
insmod helloworld.ko
uninstall:
rmmod helloworld.ko