linux内核timer执行上下文,内核定时器的使用(好几个例子add_timer)

Linux内核定时器是用于在将来某个时间点执行特定函数的机制,它在kernel/timer.c中实现。定时器函数运行在非进程上下文,不访问用户空间,不能休眠或调度。主要API包括初始化、注册、重新注册和注销。通过add_timer()激活,mod_timer()调整期限,del_timer()或del_timer_sync()注销。文章提供了多个示例演示如何使用内核定时器。
摘要由CSDN通过智能技术生成

LINUX内核定时器是内核用来控制在未来某个时间点(基于jiffies)调度执行某个函数的一种机制,其实现位于 和 kernel/timer.c 文件中。

被调度的函数肯定是异步执行的,它类似于一种“软件中断”,而且是处于非进程的上下文中,所以调度函数必须遵守以下规则:

1) 没有 current 指针、不允许访问用户空间。因为没有进程上下文,相关代码和被中断的进程没有任何联系。

2) 不能执行休眠(或可能引起休眠的函数)和调度。

3) 任何被访问的数据结构都应该针对并发访问进行保护,以防止竞争条件。

内核定时器的调度函数运行过一次后就不会再被运行了(相当于自动注销),但可以通过在被调度的函数中重新调度自己来周期运行。

在SMP系统中,调度函数总是在注册它的同一CPU上运行,以尽可能获得缓存的局域性。

定时器API

内核定时器的数据结构

struct timer_list {

struct list_head entry;

unsigned long expires;

void (*function)(unsigned long);

unsigned long data;

struct tvec_base *base;

/* ... */

};

其中 expires 字段表示期望定时器执行的 jiffies 值,到达该 jiffies 值时,将调用 function 函数,并传递 data 作为参数。当一个定时器被注册到内核之后,entry 字段用来连接该定时器到一个内核链表中。base 字段是内核内部实现所用的。

需要注意的是 expires 的值是32位的,因为内核定时器并不适用于长的未来时间点。

初始化

在使用 struct timer_list 之前,需要初始化该数据结构,确保所有的字段都被正确地设置。初始化有两种方法。

方法一:

DEFINE_TIMER(timer_name, function_name, expires_value, data);

该宏会静态创建一个名叫 timer_name 内核定时器,并初始化其 function, expires, name 和 base字段。

方法二:

struct timer_list mytimer;

setup_timer(&mytimer, (*function)(unsigned long), unsigned long data);

mytimer.expires = jiffies + 5*HZ;

方法3:

struct timer_list mytimer;

init_timer(&mytimer);

mytimer ->timer.expires = jiffies + 5*HZ;

mytimer ->timer.data = (unsigned long) dev;

mytimer ->timer.function = &corkscrew_timer; /* timer handler */

通过init_timer()动态地定义一个定时器,此后,将处理函数的地址和参数绑定给一个timer_list

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值