内核定时器init_timer与mod_timer的使用

内核定时器为了可以在某个时间点上调用函数

内核定时器的调度函数运行过一次后就不会再被运行了,
但是在del_timer销毁定时之前,可以使用add_timer(注册)或者mod_timer(修改)重新调用
一般重新调用的场景有
1 通过在被调度的函数中重新调度自己来周期运行。
2 通过某个中断服务函数中重新唤起调用
这样就可以实现while(1)循环的功能,可以用于轮询设备等工作需求。
这里被调度的函数是异步执行的。

#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/time.h>
#include <linux/timer.h>

static struct timer_list tm;
struct timeval oldtv;
static int counter;

void callback(unsigned long arg){
#if 0
    struct timeval tv;
    char *strp = (char*)arg;
    do_gettimeofday(&tv);
    printk("[%s](%s)%ld\n", __func__,strp,
        tv.tv_sec); 
    

    oldtv = tv;
    tm.expires = jiffies+1*HZ;    
	counter++;
	if(counter < 5){
    	add_timer(&tm); 
	}    
#endif

#if 1
	struct timeval tv;
	char *strp = (char*)arg;
	do_gettimeofday(&tv);
	printk("[%s](%s)%ld\n", __func__,strp,
		tv.tv_sec); 
	counter++;
	if(counter < 5){
    	mod_timer(&tm, jiffies+1*HZ); 
	}
#endif
}

static int __init demo_timer_init(void){
    printk(KERN_INFO "[%s] START.\n", __func__);
#if 0
    init_timer(&tm); 
    do_gettimeofday(&oldtv); 
    tm.function= callback; 
    tm.data    = (unsigned long)"hello world"; 
    tm.expires = jiffies+1*HZ;  
    add_timer(&tm); 
#endif

#if 1	
	init_timer(&tm); 
    do_gettimeofday(&oldtv); 
    tm.expires = jiffies+1*HZ;  
    setup_timer(&tm, callback, (unsigned long)"Hello World"); 
    add_timer(&tm); 
#endif	
	
    return 0;
}

static void __exit demo_timer_exit(void){
    printk(KERN_INFO "[%s] EXIT.\n", __func__);
    del_timer(&tm);
}

module_init(demo_timer_init);
module_exit(demo_timer_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("Mr.linux.debug");
MODULE_DESCRIPTION("Demo timer for kernel module");

以上使用中可以看出
setup_timer可以直接传入tm.function和tm.data,
替代单独给function和data赋值的过程

mod_timer 和 add_timer 使用这两者都可以实现重复调用自身。
运行结果

$ insmod demo_init_timer.ko
[demo_timer_init] START.
[callback](Hello World)1591010973
[callback](Hello World)1591010974
[callback](Hello World)1591010975
[callback](Hello World)1591010976
[callback](Hello World)1591010977

$ rmmod demo_init_timer
[demo_timer_exit] EXIT.

函数使用说明

add_timer把定时器注册连接到内核专门的链表中(最终也是通过调用mod_timer实现)
mod_timer重新注册定时器到内核专门的链表中(不管定时器函数是否被运行过)
del_timer注销一个定时器(它不会等待其他CPU上的调度结束,在单核处理器上,可以直接使用)
del_timer_sync注销一个定时器(用于SMP多核系统,会进入休眠等待其他CPU上的调度结束)
timer_pending判断一个定时器是否被添加到了内核链表中以等待被调度运行
setup_timer建个定时器 主要负责给 function 和 data 进行赋值工作

由于 add_timer 最终也是调用到 mod_timer 接口实现定时器的作用,所以需要重新调用时,
也可以使用 add_timer 进行配置定时器,以使该定时器进行计时重新调度的流程内。

Linux内核中,`add_timer`和`mod_timer`都是用于操作定时器的函数,但它们在使用场景和具体功能上有一些区别。 ### `add_timer` `add_timer`函数用于将一个已经初始化的定时器添加到系统中。如果定时器已经在运行中,`add_timer`会返回错误。因此,`add_timer`通常在定时器尚未启动时使用。 ### `mod_timer` `mod_timer`函数用于修改一个已经运行的定时器的到期时间。如果定时器尚未启动,`mod_timer`会将其启动。因此,`mod_timer`可以用于启动一个新的定时器,也可以用于修改现有定时器的到期时间。 ### 详细举例 假设我们有一个定时器需要在某个时间点触发,我们可以使用以下代码来初始化和启动定时器: ```c #include <linux/timer.h> #include <linux/jiffies.h> struct timer_list my_timer; void my_timer_callback(struct timer_list *t) { printk("Timer triggered\n"); // 重新调度定时器 mod_timer(&my_timer, jiffies + msecs_to_jiffies(1000)); } void init_timer_example(void) { timer_setup(&my_timer, my_timer_callback, 0); mod_timer(&my_timer, jiffies + msecs_to_jiffies(1000)); } void cleanup_timer_example(void) { del_timer_sync(&my_timer); } ``` 在这个例子中,`init_timer_example`函数初始化并启动了一个定时器,`my_timer_callback`是定时器的回调函数。`mod_timer`函数用于重新调度定时器,使其在1秒后再次触发。 如果我们需要修改定时器的到期时间,可以使用`mod_timer`: ```c void modify_timer_example(void) { mod_timer(&my_timer, jiffies + msecs_to_jiffies(2000)); } ``` 在这个例子中,`modify_timer_example`函数将定时器的到期时间修改为2秒后。 ### 使用`add_timer` 如果我们在定时器尚未启动时使用`add_timer`,可以这样做: ```c void add_timer_example(void) { timer_setup(&my_timer, my_timer_callback, 0); add_timer(&my_timer); } ``` 在这个例子中,`add_timer_example`函数初始化并启动了一个定时器,`add_timer`函数用于将定时器添加到系统中。 ### 总结 - `add_timer`用于将一个已经初始化的定时器添加到系统中。 - `mod_timer`用于修改一个已经运行的定时器的到期时间,也可以用于启动一个新的定时器。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值