Linux Kernel Driver 之 软件 timer

定时器

1. 指定timeout时刻执行超时处理函数

2. 一旦到期,内核会删除该定时器,超时处理函数只会执行一次

3. 定时器基于软中断实现,在定时器的处理函数中,不允许休眠

数据结构

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

expires: 不是超时时间,而是将来的某个时刻点 即 jiffies + timeout

代码

#include <linux/init.h>
#include <linux/module.h>
#include <linux/interrupt.h>
#include <linux/jiffies.h>
#include <linux/timer.h>

MODULE_DESCRIPTION("Frocheng: Driver for DEMO!");
MODULE_AUTHOR("Frodo Cheng");
MODULE_LICENSE("GPL");
MODULE_VERSION("V0.0.1");

#define HELLO_TIMEOUT_SEC       (1ULL * HZ)

static struct timer_list hello_timer;

static char* name = "HelloTimer";

static void timer_handle_cb(struct timer_list * pt)
{
    printk("===[frocheng]===[%s]===[%s]===[%d]===[%s]===\n",__FILE__, __func__, __LINE__, name);
    mod_timer(&hello_timer, jiffies + 2 * HELLO_TIMEOUT_SEC);
}


static int __init hello_init(void)
{
    printk("===[frocheng]===[%s]===[%s]===[%d]===[Hello !]===\n",__FILE__, __func__, __LINE__);
    hello_timer.expires = jiffies + 2 * HELLO_TIMEOUT_SEC;
    init_timer_key(&hello_timer, timer_handle_cb, 0, name, NULL);
    add_timer(&hello_timer);
    return 0;
}

static void __exit hello_exit(void)
{
    del_timer(&hello_timer);
    printk("===[frocheng]===[%s]===[%s]===[%d]===[Bye bye...]===\n",__FILE__, __func__, __LINE__);
}

module_init(hello_init);
module_exit(hello_exit);

由于超时处理函数中,有一个prink的操作,便不试验了,把这个printk的操作,放到工作队列中去处理。

代码,工作队列

#include <linux/init.h>
#include <linux/module.h>
#include <linux/interrupt.h>
#include <linux/jiffies.h>
#include <linux/timer.h>

MODULE_DESCRIPTION("Frocheng: Driver for DEMO!");
MODULE_AUTHOR("Frodo Cheng");
MODULE_LICENSE("GPL");
MODULE_VERSION("V0.0.1");

#define HELLO_TIMEOUT_SEC       (1ULL * HZ)

static struct timer_list hello_timer;
static struct work_struct w;

static char* name = "HelloTimer";

static void wq_handle_cb(struct work_struct * w)
{
    printk("===[frocheng]===[%s]===[%s]===[%d]===[%s]===\n",__FILE__, __func__, __LINE__, name);
}

static void timer_handle_cb(struct timer_list * pt)
{
    mod_timer(&hello_timer, jiffies + 2 * HELLO_TIMEOUT_SEC);
	schedule_work(&w);
}


static int __init hello_init(void)
{
    printk("===[frocheng]===[%s]===[%s]===[%d]===[Hello !]===\n",__FILE__, __func__, __LINE__);
	INIT_WORK(&w, wq_handle_cb);
    hello_timer.expires = jiffies + 2 * HELLO_TIMEOUT_SEC;
    init_timer_key(&hello_timer, timer_handle_cb, 0, name, NULL);
    add_timer(&hello_timer);
    return 0;
}

static void __exit hello_exit(void)
{
    del_timer(&hello_timer);
    printk("===[frocheng]===[%s]===[%s]===[%d]===[Bye bye...]===\n",__FILE__, __func__, __LINE__);
}

module_init(hello_init);
module_exit(hello_exit);

结果

注意:

由于是 ONE SHOT 方式的timer,如果需要循环的执行,那么就需要在 callback 中

1. 不断的更新 expires 域的值

2. 不断的add_timer

3. 为了安全 在 1,2之前先 del_timer(),因为,如果执行到了处理函数,内核已经执行了 del_timer(),但是即便如此,此时 del_timer() 也无影响。

但是以上三步的执行路径并不具备原子性,所以用一个 mod_timer(),一个原子性操作的接口,完成以上三步。

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值