• 周四. 12月 1st, 2022

5G编程聚合网

5G时代下一个聚合的编程学习网

热门标签

[Linux] driver-15-timer

[db:作者]

1月 6, 2022
Catalog
  • Preface
  • 15. Timer
    • 15.1 Kernel function summary
    • 15.2 Kernel tick
    • 15.3 Related structures
    • 15.4 setup_timer() Set the timer
    • 15.5 add_timer() Add timers to the kernel
    • 15.6 mod_timer() Modify timer timeout
    • 15.7 del_timer Delete timer

Preface

15. Timer

This chapter is one of the driving cornerstones .
The driver only provides functions , No policy provided .

original text :https://www.cnblogs.com/lizhuming/p/14922233.html

Reference source path :include\linux\timer.h

Refer to examples to see how to use .

15.1 Kernel function summary

KERNEL Use .

explain : The following is just part of it API nothing more . by Linux5.12.8 edition . There are others. API Can realize the function of kernel timer , Refer to the kernel documentation for details .

  • setup_timer(): Set the timer .
  • add_timer(): Add timers to the kernel .
  • mod_timer(): Modify timer timeout .
  • del_timer(): Delete timer .

15.2 Kernel tick

obtain CONFIG_HZ:

  1. stay Linux Found in the root directory of the kernel source code .config The configuration file . Open the file and find the macro CONFIG_HZ , This macro defines the kernel tick (tick) frequency .
  2. Command line : Get into /boot, Find files config-5.8.0-53-geberic( Systems , The file names are different , Just look at the prefix ) Content .
  • As ordered :grep ^CONFIG_HZ /boot/config-$(uname -r) .
  1. APP:sysconf(_SC_CLK_TCK) .

kernel tick
Every beat , Kernel global values jiffies It will add up 1.

The time value of the timer is based on jiffies Of .

therefore , In fact, we can also compare the settings Tick value and jiffies To see if it’s time-out . thus , The kernel recommends the following 4 individual API:

/*
* These inlines deal with timer wrapping correctly. You are
* strongly encouraged to use them
* 1. Because people otherwise forget
* 2. Because if the timer wrap changes in future you won't have to
* alter your driver code.
*
* time_after(a,b) returns true if the time a is after time b.
*
* Do this with "<0" and ">=0" to only test the sign of the result. A
* good compiler would generate better code (and a really good compiler
* wouldn't care). Gcc is currently neither.
*/
#define time_after(a,b) \
(typecheck(unsigned long, a) && \
typecheck(unsigned long, b) && \
((long)((b) - (a)) < 0))
#define time_before(a,b) time_after(b,a)
#define time_after_eq(a,b) \
(typecheck(unsigned long, a) && \
typecheck(unsigned long, b) && \
((long)((a) - (b)) >= 0))
#define time_before_eq(a,b) time_after_eq(b,a)

timer_list:

struct timer_list {
/*
* All fields that change during normal runtime grouped to the
* same cacheline
*/
struct hlist_node entry;
unsigned long expires; // Timeout time
void (*function)(struct timer_list *); // Callback function
u32 flags; // sign
#ifdef CONFIG_LOCKDEP
struct lockdep_map lockdep_map;
#endif
};

15.4 setup_timer() Set the timer

function : Set the timer . initialization timer_list Structure .

The function prototype

/**
* timer_setup - prepare a timer for first use
* @timer: the timer in question
* @callback: the function to call when timer expires
* @flags: any TIMER_* flags
*
* Regular timer initialization should use either DEFINE_TIMER() above,
* or timer_setup(). For timers on the stack, timer_setup_on_stack() must
* be used and must be balanced with a call to destroy_timer_on_stack().
*/
#define timer_setup(timer, callback, flags) \
__init_timer((timer), (callback), (flags))

15.5 add_timer() Add timers to the kernel

function : Add timers to the kernel .

The function prototype

/**
* add_timer - start a timer
* @timer: the timer to be added
*
* The kernel will do a ->function(@timer) callback from the
* timer interrupt at the ->expires point in the future. The
* current time is 'jiffies'.
*
* The timer's ->expires, ->function fields must be set prior calling this
* function.
*
* Timers with an ->expires field in the past will be executed in the next
* timer tick.
*/
void add_timer(struct timer_list *timer)
{
BUG_ON(timer_pending(timer));
__mod_timer(timer, timer->expires, MOD_TIMER_NOTPENDING);
}
EXPORT_SYMBOL(add_timer);

15.6 mod_timer() Modify timer timeout

function : Modify timer timeout .

notes : In the notes , Modifying the timeout is equivalent to deleting the timer and adding it to the kernel again . explain , You can’t simply use it after adding it to the kernel imer->expires = expires; To modify the timeout .

The function prototype

/**
* mod_timer - modify a timer's timeout
* @timer: the timer to be modified
* @expires: new timeout in jiffies
*
* mod_timer() is a more efficient way to update the expire field of an
* active timer (if the timer is inactive it will be activated)
*
* mod_timer(timer, expires) is equivalent to:
*
* del_timer(timer); timer->expires = expires; add_timer(timer);
*
* Note that if there are multiple unserialized concurrent users of the
* same timer, then mod_timer() is the only safe way to modify the timeout,
* since add_timer() cannot modify an already running timer.
*
* The function returns whether it has modified a pending timer or not.
* (ie. mod_timer() of an inactive timer returns 0, mod_timer() of an
* active timer returns 1.)
*/
int mod_timer(struct timer_list *timer, unsigned long expires)
{
return __mod_timer(timer, expires, 0);
}
EXPORT_SYMBOL(mod_timer);

15.7 del_timer Delete timer

function : Delete timer .

The function prototype

/**
* del_timer - deactivate a timer.
* @timer: the timer to be deactivated
*
* del_timer() deactivates a timer - this works on both active and inactive
* timers.
*
* The function returns whether it has deactivated a pending timer or not.
* (ie. del_timer() of an inactive timer returns 0, del_timer() of an
* active timer returns 1.)
*/
int del_timer(struct timer_list *timer)
{
struct timer_base *base;
unsigned long flags;
int ret = 0;
debug_assert_init(timer);
if (timer_pending(timer)) {
base = lock_timer_base(timer, &flags);
ret = detach_if_pending(timer, base, true);
raw_spin_unlock_irqrestore(&base->lock, flags);
}
return ret;
}
EXPORT_SYMBOL(del_timer);

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注