当前位置:首页>Linux>Linux内核定时器

Linux内核定时器

  • 2026-10-04 14:39:30
Linux内核定时器

Linux内核时钟配置

Linux内核可选的配置系统频率

  • 100HZ
  • 200HZ
  • 250HZ
  • 300HZ
  • 500HZ
  • 1000HZ

默认情况下选择的是100HZ。

对应.config配置文件的内容:

CONFIG_HZ_100=yCONFIG_HZ=100

对应到内核源码include/arm-generic中的配置:

#ifndef __ASM_GENERIC_PARAM_H#define __ASM_GENERIC_PARAM_H#include<uapi/asm-generic/param.h># undef HZ# define HZ        CONFIG_HZ    /* Internal kernel timer frequency */# define USER_HZ    100        /* some user interfaces are */# define CLOCKS_PER_SEC    (USER_HZ)       /* in "ticks" like times() */#endif/* __ASM_GENERIC_PARAM_H */

宏HZ的值是一秒节拍数(频率)

Linux内核使用jiffies全局变量来记录系统节拍数。

include/linux/jiffies.h

extern u64 __cacheline_aligned_in_smp jiffies_64;externunsignedlongvolatile __cacheline_aligned_in_smp __jiffy_arch_data jiffies;

Linux中处理jiffies溢出的函数

time_after(unkown, known)  //如果ununkown超过known返回真,否则返回假time_before(unkown, known)  //如果ununkown没有超过known返回真,否则返回假time_after_eq(unkown, known) time_before_eq(unkown, known) //unkown 通常为 jiffies//known 通常是需要对比的值。

超时判断示例代码:

unsignedlong timeout;timeout = jiffies + (3 * HZ);     //超时时间点,即3s后超时//超时判断if (time_after(jiffies, timeout))    //超时{    ...        //超时}else{    ...}

Linux内核提供的jiffies和ms、us、ns之间的转换函数

intjiffies_to_msecs(constunsignedlong j)intjiffies_to_usecs(constunsignedlong j)u64 jiffies_to_nsecs(constunsignedlong j)longmsecs_to_jiffies(constunsignedint m)longusecs_to_jiffies(constunsignedint u)unsignedlongnsecs_to_jiffies(u64 n)

Linux内核定时器

include/linux/timer.h

structtimer_list {/*     * All fields that change during normal runtime grouped to the     * same cacheline     */structhlist_nodeentry;unsignedlong        expires;void            (*function)(struct timer_list *);    u32            flags;#ifdef CONFIG_LOCKDEPstructlockdep_maplockdep_map;#endif}

定时器超时后就会停止,需要周期定时就要在超时函数中重新启动定时器

定时器API

//void init_timer(struct timer_list *timer)    //初始化定时器//timer 要初始化的定时器#define __TIMER_INITIALIZER(_function, _flags) {        \        .entry = { .next = TIMER_ENTRY_STATIC },    \        .function = (_function),            \        .flags = (_flags),                \        __TIMER_LOCKDEP_MAP_INITIALIZER(        \            __FILE__ ":" __stringify(__LINE__))    \    }//定义一个名为_name,超时回调函数为_function的定时器,并初始化#define DEFINE_TIMER(_name, _function)                \    struct timer_list _name =                \        __TIMER_INITIALIZER(_function, 0)
voidadd_timer(struct timer_list *timer)//向内核注册定时器,注册后就开始运行
intdel_timer(struct timer_list * timer)//删除定时器intdel_timer_sync(struct timer_list *timer)//返回0表示定时器没有被启动,返回1表示定时器已经被启动。
intmod_timer(struct timer_list *timer, unsignedlong expires)//修改超时时间,如果定时器没有启动,修改后启动定时器//返回0表示修改expires前已经被启动没有启动,1表示expires修改前已经被启动

定时器一般使用模板

structtimer_listtimer;//定时定时器//定时超时回调函数voidtimeout_callback(unsignedlong arg){/* 超时处理代码 *///周期运行需要调用mod_timer重新启动定时器    mod_timer(&dev->timertest, jiffies + msecs_to_jiffies(2000)); }voidtimer_init(void){    init_timer(&timer);                  /* 初始化定时器 */    timer.function = timeout_callback;                 /* 设置定时处理函数 */    timer.expires  = jffies + msecs_to_jiffies(2000);  /* 设置超时时间为 2 秒 */    timer.data = (unsignedlong)&dev;  /* 将设备结构体作为参数  */    add_timer(&timer);             /* 将内核注册启动定时器 * /   }
voidtimer_deinit(void){    del_timer(&timer);}

Linux内核延时

Linux提供的短延时函数

voidndelay(unsignedlong nsecs)voidudelay(unsignedlong usecs)voidmdelay(unsignedlong mseces)//三个函数都是忙等待延时函数,进程不会进入休眠

长延时

//忙等待长延时/*  延迟 100 个 jiffies */unsignedlong delay = jiffies + 100;while(time_before(jiffies, delay));/*  再延迟 2s */unsignedlong delay = jiffies + 2*Hz;while(time_before(jiffies, delay));

进程休眠延时

//将当前进程添加到等待队列中,从而在等待队列上睡眠  interruptible_sleep_on_timeout可以被中断打断sleep_on_timeout(wait_queue_head_t *q, unsignedlong timeout);interruptible_sleep_on_timeout(wait_queue_head_t*q, unsignedlong timeout);   
//此二者本质是调用上面的sleep_on_timeout和interruptible_sleep_on_timeout实现的voidmsleep(unsignedint msecs)//毫秒延时unsignedlongmsleep_interruptible(unsignedint msecs)//毫秒延时,可以被中断打断

最新文章

随机文章