0
点赞
收藏
分享

微信扫一扫

linux驱动 定时器

有点d伤 2022-02-03 阅读 56
linux

目录

1.1、CONFIG_HZ

2、jiffies

2.1、jiffies_64

2.2、系统运行时间

2.3、时间绕回

3、API函数

4、内核定时器

4.1、timer_list结构体

4.2、init_timer()函数

4.3、add_timer()函数

4.4、del_timer()函数

4.5、del_timer_sync()函数

4.6、mod_timer()函数

5、Linux 内核短延时函数


1、设置系统节拍率

在编译 Linux 内核的时候可以通过图形化界面设置系统节拍率。

-> Kernel Features
    -> Timer frequency

1.1、CONFIG_HZ

HZ 表示一秒的节拍数,Linux 内核会使用 CONFIG_HZ 来设置自己的系统时钟(include/asm-generic/param.h)

#undef HZ
#define HZ CONFIG_HZ
#define USER_HZ 100
#define CLOCKS_PER_SEC (USER_HZ)

2、jiffies

Linux 内核使用全局变量 jiffies 来记录系统从启动以来的系统节拍数(jiffies 定义在文件 include/linux/jiffies.h 中)。

#define __jiffy_data  __attribute__((section(".data")))

extern u64 __jiffy_data jiffies_64;
extern unsigned long volatile __jiffy_data jiffies;

2.1、jiffies_64

jiffies_64 用于 64 位系统,而 jiffies 用于 32 位系统。为了兼容不同的硬件, jiffies 其实就是 jiffies_64 的低 32 位。

2.2、系统运行时间

HZ 表示每秒的节拍数, jiffies 表示系统运行的 jiffies 节拍数,所以 jiffies/HZ 就是系统运行时间,单位为秒。

2.3、时间绕回

不管是 32 位还是 64 位的 jiffies,都有溢出的风险,溢出以后会重新从 0 开始计数。假如 HZ 为最大值 1000 的时候, 32 位的 jiffies 只需要 49.7 天就发生了绕回,对于 64 位的 jiffies 来说大概需要5.8 亿年才能绕回,因此 jiffies_64 的绕回忽略不计。

3、API函数

时间比较函数
time_after(unkown, known)如果 unkown 超过 known 的话,返回真,否则返回假。
time_before(unkown, known)如果 unkown 没有超过 known 的话,返回真,否则返回假。
time_after_eq(unkown, known)如果 unkown 超过或等于 known 的话,返回真,否则返回假。
time_before_eq(unkown, known)如果 unkown 没有超过或等于 known 的话,返回真,否则返回假。
jiffies 和 ms、 us、 ns 之间的转换函数
int jiffies_to_msecs(const unsigned long j)将 jiffies 类型转换为对应的毫秒。
int jiffies_to_usecs(const unsigned long j)将 jiffies 类型转换为对应的微秒。
u64 jiffies_to_nsecs(const unsigned long j)将 jiffies 类型转换为对应的毫秒纳秒。
long msecs_to_jiffies(const unsigned int m)将毫秒转换为 jiffies 类型。
long usecs_to_jiffies(const unsigned int u)将微秒转换为 jiffies 类型。
unsigned long nsecs_to_jiffies(u64 n)将纳秒转换为 jiffies 类型。

4、内核定时器

内核定时器并不是周期性运行的,超时以后就会自动关闭,因此如果想要实现周期性定时,那么就需要在定时处理函数中重新开启定时器(定义在include/linux/timer.h中)。

4.1、timer_list结构体

Linux 内核使用 timer_list 结构体表示内核定时器。

struct timer_list {
	struct list_head entry;
	unsigned long expires;
	struct tvec_base *base;

	void (*function)(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
}
entry链表节点
expires定时器超时时间,单位为节拍数
function定时处理函数
data要传递给 function 函数的参数

4.2、init_timer()函数

init_timer 函数负责初始化 timer_list 类型变量。

void init_timer(struct timer_list *timer)

参数 timer:要初始化定时器。

4.3、add_timer()函数

add_timer 函数用于向 Linux 内核注册定时器。

void add_timer(struct timer_list *timer)

参数 timer:要注册的定时器。

4.4、del_timer()函数

del_timer 函数用于删除一个定时器,不管定时器有没有被激活,都可以使用此函数删除。

int del_timer(struct timer_list * timer)

timer:要删除的定时器。
返回值: 0,定时器还没被激活; 1,定时器已经激活。


注:在多处理器系统上,定时器可能会在其他的处理器上运行,因此在调用 del_timer 函数删除定时器之前要先等待其他处理器的定时处理器函数退出。

4.5、del_timer_sync()函数

del_timer_sync 函数是 del_timer 函数的同步版,会等待其他处理器使用完定时器再删除,
del_timer_sync 不能使用在中断上下文中。

int del_timer_sync(struct timer_list *timer)

timer:要删除的定时器。
返回值: 0,定时器还没被激活; 1,定时器已经激活。

4.6、mod_timer()函数

mod_timer 函数用于修改定时值,如果定时器还没有激活的话, mod_timer 函数会激活定时器

int mod_timer(struct timer_list *timer, unsigned long expires)

timer:要修改超时时间(定时值)的定时器。
expires:修改后的超时时间。
返回值: 0,调用 mod_timer 函数前定时器未被激活; 1,调用 mod_timer 函数前定时器已
被激活。
 

5、Linux 内核短延时函数

void ndelay(unsigned long nsecs)纳秒延时函数。
void udelay(unsigned long usecs)微秒延时函数。
void mdelay(unsigned long mseces)毫秒延时函数。


 

举报

相关推荐

0 条评论