《Linux 内核定时器》之iPhone13真香

  • Post author:
  • Post category:linux




iPhone13真香系列

iphone 的发布会在9月17号,我的一位小伙伴,在发布会结束之后就下单,晒在了朋友圈。作为一个,作为一个爱国主义着,当然要支持国产品牌。最主要的原因:一些品牌吃着中国的饭,砸着中国的碗。像前段时间的H&W的一些知名品牌,做出”停用中国棉花”的决定,所以本人也是内心很抵制一些非国产品牌。

在这里插入图片描述

但是,第二天我俩聊天 , 12期免息,一个月500,还是值得入手的,啊,真香 !在真香的同时,希望苹果不要做“吃着中国的饭,还砸着中国的锅”!!!H&W就是个例子,天下哪有这样的美事。

在这里插入图片描述

linux 内核定时器


一:简介


我们在开发单片机和裸机时,会经常用到定时器,是由一个硬件的定时器提供系统时钟,在rtos系统中一般使用Systick作为系统时钟。同样的在linux中,也是需要一个系统时钟。

在内核中有大量的需要函数需要时间管理,比如周期性的程序调度,延时程序。对于驱动开发人员来说,最常用的就是定时器。硬件定时器提供时钟源,时钟源的频率可以设置。设置好之后,就会产生周期性性的中断,系统使用使用中断来计时。中断周期性产生的频率就是系统频率,也叫节拍率,比如100HZ 、500HZ等都是系统节拍率。


二:系统节拍率


1. 系统节拍率时可以设置的,单位时HZ,可以通过如下方法来进行设置:

文件kernel/include/asm-generic/param.h

#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宏,宏HZ=CONFIG_HZ=100,在驱动编写会经常使用到HZ,因为HZ表示的就是一秒的节拍数,也就是频率。
//这里存在一个问题,系统节拍HZ为100Hz,时间精度就是10ms,采用高节拍HZ,比如1000hz,时间精度就是1ms,引出了一个高节拍率和低节拍率优缺点问题:1)高精度时钟的好处有很多,对于时间要求严格的函数来说,能够以更高精度运行,时间测量也更加精准。毕竟时间精度从10ms---1ms,精度提高了10倍。
	(2)高精度提高时间精度的同时,产生的中断也是10倍,这样中断产生的更加频繁,加剧系统的负担。中断服务处理函数占用处理器时间增加,增加系统负载的压力

2.系统使用全局变量jiffes来记录系统节拍数,在我们日常使用的手机 Android系统中,会看到系统以及开机多长时间或者运行了多长时间。就是jiffes来记录的,在系统启动时,初始化为0,然后记录。

jiffies定义在kernel/include/linux/jiffies.h

extern u64 __cacheline_aligned_in_smp jiffies_64;
extern unsigned long volatile __cacheline_aligned_in_smp __jiffy_arch_data jiffies;
//可以看到定义了u64 64bit的jiffies_64,undigned long 32bit 的jiffies。64bit和32bit定义的jiffies其实是相同的。64bit用于64为系统,32bit运用与32bit系统。内核这样做的目的,是为了兼容不同硬件,jiffies_64的低32bit就是jiffies。

3.HZ代表每秒的节拍数,jiffies表示系统的节拍数,所以jiffies/HZ就是系统运行的时间,单位为s。不管32bit、64bit都有溢出的风险,溢出之后会从0从新计数,这个现象叫做绕回,64bit系统需要5.8亿年才能绕回,32bit50天左右会绕回。所以处理32bit的绕回对我们来说很重要。

api:

(1) //a通常为jiffies,b为要对比的value.
time_after(a,b) //a>b,return=true
time_before(a,b)//a<b,return=true
time_after_eq(a,b)//类似
time_before_eq(a,b)//

(2) //时间转换函数
extern unsigned int jiffies_to_msecs(const unsigned long j);//jiffies-->ms
extern unsigned int jiffies_to_usecs(const unsigned long j);//jiffies-->us
static inline u64 jiffies_to_nsecs(const unsigned long j)//jiffies-->nu

static inline unsigned long _msecs_to_jiffies(const unsigned int m)//ms-->jiffies
extern unsigned long __usecs_to_jiffies(const unsigned int u);//us-->jiffies


二:定时器


作为一个常用的功能,在使用上也是很简单的,只需要设置超时时间和定时处理函数即可。当时间到了,定时处理函数就会执行。但是要注意一点:内核定时器并不是周期运行,超市自动关闭。因此要实现周期性定时,需要在定时处理函数中重新开启定时器。

1. 内核定时器结构体,timer_list:

struct timer_list {
 struct list_head entry;
 unsigned long expires; /* 定时器超时时间,单位是节拍数 */
 struct tvec_base *base;
 void (*function)(unsigned long); /* 定时处理函数 */
 unsigned long data; /* 要传递给 function 函数的参数 */
 int slack;
};

使用之前要先定义一个time_list变量,表示定时器。expies表示超时时间,单位为节拍数。fuction就是定时器超时之后处理函数,data是函数参数。

2.定时器相关api函数

void init_timer(struct timer_list *timer)//初始化定时器结构体
void add_timer(struct timer_list *timer)//向内核注册定时器
int del_timer(struct timer_list * timer)//删除定时器,多核,需等待其他核定时器退出在删除。
int del_timer_sync(struct timer_list *timer)//等待其他处理器使用完定时器在删除,不能用于中断上下文。

int mod_timer(struct timer_list *timer, unsigned long expires)//用于修改定时器的值,如果定时器还没激活,mod_timer会定时激活。


3.内核定时器使用流程

//1.定义定时器
struct timer_list timer;

void function(unsigned long arg)
{
	//定时器处理函数

	//5.重置超时值,启动定时器;并且需要周期性运行使用mod_timer
	mod_timer(&dev->timertest, jiffies + msecs_to_jiffies(2000));
}

void init(void{
	//2.初始化
	init_timer(&timer); //初始化定时器
	
	//3.设置函数和超时时间
	timer.function = functuion;//设置定时器处理函数
	timer.expires = jiffies + mesce_to_jiffies(2000);//超时时间为2s
	timer.data = (unsigned long)*dev;//将设备结构体作为参数
	
	//4.向内核注册定时器
	add_timer(&timer);
}

void exit(vid)
{	
	//6.删除
	del_timer(&timer); //删除定时器
	//or
	del_timer_sync(&timer);
}


4.相关延时函数:

void ndelay(unsigned long nsecs) //ns
void udelay(unsigned long usecs) //us
void mdelay(unsigned long meseces) //ms

总结:


1.节拍率HZ ,节拍数jiffies,系统启动时间jiffie/HZ;


2. 定时器使用流程1、2、3、4、5、6;

3. ms、us、ns延时函数。



版权声明:本文为m0_57123509原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。