内核定时器timer_list

内核在时钟中断发生后执行检测各个定时器是否到期,到期后的定时器处理函数将作为软中断在底半部执行。实质上,时钟中断处理程序会唤起TIMER_SOFTIRQ软中断,运行当前处理器上到期的所有定时器。linux提供的内核定时器数据结构为timer_list。

一. 定义

timer_list定义在linux/timer.h中,实现在kernel/timer.c中。

struct timer_list {
    struct list head_entry;
    unsigned long expires;    //到期时间
    struct tves_base *base;

    void (*func)(unsigned long);
    unsigned long data;

    int slack;

#ifdef CONFIG_TIMER_STATS
    int start_pid;
    void *start_site;
    char start_comm[16];
#endif

#ifdef CONFIG_LOCKDEP
    struct lockdep_map lockdep_map;
#endif

};

内核相关定义:HZ和jiffies

HZ  时钟频率
jiffies 32位无符号数,当前时钟计数

# define HZ     CONFIG_HZ   /* Internal kernel timer frequency */
# define USER_HZ    100     /* some user interfaces are */
linux/jiffies.h
/*
 * The 64-bit value is not atomic - you MUST NOT read it
 * without sampling the sequence number in jiffies_lock.
 * get_jiffies_64() will do this for you as appropriate.
 */
extern u64 __jiffy_data jiffies_64;
extern unsigned long volatile __jiffy_data jiffies;

#if (BITS_PER_LONG < 64) 
u64 get_jiffies_64(void);
#else
static inline u64 get_jiffies_64(void)
{
    return (u64)jiffies;
}
#endif

二. 函数

初始化定时器

init_timer(&mytimer);

DEFINE_TIMER(_name, _function, _expires, _data);

TIMER_INITIALIZER(_function, _expires, _data);

setup_timer(timer, fn, data);

首次使能定时器

add_timer(&mytimer);
再次使能定时器

mod_timer(&mytimer, unsigned long expires);
删除定时器

del_timer_sync(&mytimer); //删除前要等待定时器处理完,不能发生在中断上下文。

del_timer(&mytimer); //删除定时器

三. 示例

#include <linux/init.h>
#include <linux/module.h>
#include <asm/current.h>
#include <linux/timer.h>
#inlcude <linux/sched.h>

MODULE_LISENCE("GPL");

extern struct task_struct *current;

struct timer_list mytimer;

void timer_handler(unsigned long arg)
{
    printk("timer arg = %d\n", arg);
    mod_timer(&mytimer, jiffies + HZ * 5);

    return;
}

static int __init akae_init(void)
{
    int local = 0;

    printk("module name is %s\n", KBUILD_MODNAME);
    printk("akae_init at %p\n", akae_init);

    printk("jiffies at %p\n", &jiffies);
    printk("jiffies is %ld\n", jiffies);

    printk("The process is \"%s\" (pid %i)\n", current->name, curent->pid);
    
    init_timer(&mytimer);

    printk("HZ is %d\n", HZ);
    mytimer.expires = jiffies + HZ * 5;
    mytimer.function = timer_handler;
    mytimer.data = 100;

    add_timer(&mytimer);

    return 0;
}

static void __exit akae_exit(void)
{
    printk("module eixt.\n");
    printk("akae_exit at %p\n", akae_exit);

    del_timer_sync(&mytimer);

    return;
}

module_init(akae_init);
module_exit(akae_exit);
posted @ 2018-03-13 20:22  yuxi_o  阅读(763)  评论(0编辑  收藏  举报