jiffies与HZ、定时器、原子操作

  • 前言
  • 一、Jiffies与HZ
    • 1、jiffies:
    • 2、HZ:
    • 3、时间与jiffies转换
    • 4、jiffies的回绕
  • 二、计时、延迟与睡眠
    • 1、计时
    • 2、延迟
    • 3、睡眠
  • 三、定时器
    • 1、简单定时器
    • 2、高精度定时器
  • 四、原子操作
    • 1、atomic_t数据类型
    • 2、操作API

前言

内核中定时器有两种,简单定时器和高精度定时器,
简单定时器:以全局变量jiffies衡量
高精度定时器:ktime 的特殊数据类型表示 有绝对时间和相对时间概念
原子操作:在多进程(线程)的操作系统中不能被其它进程(线程)打断的操作就叫原子操作,文件的原子操作是指操作文件时的不能被打断的操作。原子操作是不可分割的,在执行过程中不会被任何其它任务或事件中断。


一、Jiffies与HZ

1、jiffies:

是一个变量,每次当定时器中断发生时,内核内部通过一个64位的变量jiffies_64做加一计数。驱动程序开发者通常访问的是jiffies变量,它是jiffies_64的低32位。
jiffies是unsigned long型的变量,该变量被声明为volatile(直接从对应的内存当中提取 ),这样可避免编译器对访问该变量的语句的优化(由于访问寄存器的速度要快过RAM,所以编译器一般都会作减少存取外部RAM的优化 ) 。

2、HZ:

HZ 即表示每秒钟产生的定时中断次数
HZ就代表1秒

在 Linux 2.6 中,系统时钟每 10ms中断一次(时钟频率,用 HZ 宏表示,定义为 100,即每秒中断 100 次,这个时间单位称为一个 jiffie(如10ms)HZ=jiffies+100次

3、时间与jiffies转换

将以秒为单位的时间转化为jiffies:seconds * Hz
将jiffies转化为以秒为单位的时间:jiffies / Hz

4、jiffies的回绕

因为jiffies为unsigned long 的数据类型 防止因回绕产生错误的方法是将它转换为 long (有符号的补码可以进行比较)

避免回绕API:

二、计时、延迟与睡眠

1、计时

提供两套时间计数的方法
①、timeval

一、用户空间的timeval:
struct timeval {time_t    tv_sec;   /* 秒 */suseconds_t   tv_usec; /* 毫秒 */
};
获取当前时间:
void do_gettimeofday(struct timeval *tv);jiffies值和timeval之间转换:
unsigned long timeval_to_jiffies(struct timeval *value);
void jiffies_to_timeval(unsigned long jiffies,struct timeval *value);

②、timespec

二、用户空间的timespec:
struct timespec {time_t     tv_sec;   /* 秒 */long   tv_nsec;    /* 纳秒 */
};获取当前时间:
struct timespec current_kernel_time(void);jiffies值和timespec之间转换:
unsigned long timespec_to_jiffies(struct timespec *value);
void jiffies_to_timespec(unsigned long jiffie, struct timespec *value);

2、延迟

延时实际上是忙等待,cpu空跑一段代码
①、长延时

while(time_before(jiffies,end_time)){//等待超时schedule();//休眠,让出CPU,内核调度其他进程
}signed long schedule_timeout(signed long timeout);典例
set_current_state(TASK_INTERRUPTIBLE);
schedule_timeout(delay);

②、短延时
这三个延迟函数均是忙等待函数,因而在延迟过程中,时间片未到时,内核不会调度其他进程,即无法运行其他任务。表象上看,就是系统很卡,CPU资源被一直耗用这。所以 要特别慎用此类函数。

void ndelay(unsigned long nsecs);   /*延时纳秒*/
void udelay(unsigned long usecs);   /*延时微妙*/
void mdelay(unsigned long msecs);    /*延时毫秒*/

3、睡眠

这2个延迟函数是不使用忙等待的延迟函数,因而在延迟过程中,调用该函数的进程会主动调用schedule,即让出CPU,内核调度其他进程运行。

void msleep(unsigned int millisecs);
unsigned long msleep_interruptible(unsigned int millisecs);

三、定时器

定时器的使用很简单。你只需要执行一些初始化工作,设置一个超时时间,指定超时发生后执行的函数,然后激活定时器就可以了。
定时器有两种 简单定时器和高精度定时器
定时器并不是周期运行,它在超时后就自行销毁

1、简单定时器

简单定时器结构体

定时器由结构timer_list表示,在<linux/timer.h>中:struct timer_list{struct list_head entry;    /*定时器链表入口*/unsigned long expires;    /*以jiffies单位的定时值*/spin_lock lock;       /*保护定时器的锁*/void (*func)(unsigned long); /* 定时器处理函数*/ unsigned long data;        /*参数*/  struct tvec_t_base_s *base;   /*定时内部值,用户不要使用*/
};

使用定时步骤:

1、定义定时器:struct timer_list my_timer;
2、初始化定时器:init_timer(&my_timer);
3、定义定时器中断处理函数:
void my_timer_fuc(unsigned long data);
例:
init_timer(&my_timer);
my_timer.function = my_timer_fuc;
my_timer.data = 0;
my_timer.expires = xxx; //超时时间
add_timer(&my_timer); //添加到内核、启动定时器
data参数使你可以利用同一个处理函数注册多个定时器,只需要通过参数就能区别对待它们。如果不需要参数,可以简单的传递0(或任何其他值)给处理函数。
----以上三个步骤可以用以下直接代替
①、static struct timer_list my_timer =TIMER_INITIALIZER(_function, _expires, _data);
②、setup_timer(timer, fn, data);
设置定时器,主要是初始化 timer_list 结构体,设置其中的函数、参数。
4、添加定时器到内核(启动)
void add_timer(struct timer_list *timer):
向内核添加定时器。timer->expires 表示超时时间。
当超时时间到达,内核就会调用这个函数:timer->function(timer->data)。
5、修改定时器值
mod_timer(&my_tiner, jiffies+new_delay );
第2个参数表示超时时间,它是以节拍为单位的绝对计数值 ,只要节拍计数大于或等于指定的超时时,内核就开始执行定时器处理函数,然后停止计时。
6、停止定时器
①、del_timer(&my_timer);
被激活或未被激活的定时器都可以使用该函数。如果定时器还未被激活,该函数返回0;否则返回1。
②、del_timer_sync(&my_timer);
同步等待可能在其他处理器上运行的定时器处理程序都退出、不能在中断上下文中使用
例:
//初始化
setup_timer(&key_timer, key_timer_expire, &gpio_keys);
key_timer.expires = ~0; //设置定时时间
add_timer(&key_timer); //添加到内核启动定时器
/修改值
mod_timer(&key_timer, jiffies+new_delay) //修改定时器的值

2、高精度定时器

尽管简单计时器 API 简单有效,但它并不能提供实时应用程序所需的准确性。为此,内核引入了精确度更高的计时器。
注意:时间不是用 jiffies 表示的,而是以一种名为 ktime 的特殊数据类型表示。这种表示方法隐藏了在这个粒度上有效管理时间的一些细节。hrtimer API 正式确认(formalize)了绝对时间相对时间之间的区别,要求调用者指定类型。

①、初始化定时器:
void hrtimer_init( struct hrtimer *time, clockid_t clock_id, enum hrtimer_mode mode );
其中,第二个参数clock_id有两种取值,如下:
CLOCK_REALTIME:这种类型的时钟可以反映wall clock time,用的是绝对时间,当系统的时钟源被改变,或者系统管理员重置了系统时间之后,这种类型的时钟可以得到相应的调整,也就是说,系统时间影响这种类型的timer。
CLOCK_MONOTONIC:用的是相对时间,他的时间是通过jiffies值来计算的。该时钟不受系统时钟源的影响,只受jiffies值的影响。
建议使用:CLOCK_MONOTONIC这种时钟更加稳定,不受系统时钟的影响。如果想反映wall clock time,就使用CLOCK_REALTIME。
②、 启动定时器 :
int hrtimer_start(struct hrtimer *timer, ktime_t time, const enum hrtimer_mode mode);
③、取消计时器:
int hrtimer_cancel(struct hrtimer *timer);
如果计时器已经发出,那么它将等待回调函数结束
int hrtimer_try_to_cancel(struct hrtimer *timer);
如果计时器已经发出,它将返回失败

四、原子操作

所谓原子操作,就是该操作绝不会在执行完毕前被任何其他任务或事件打断,也就说,它的最小的执行单位,不可能有比它更小的执行单位。
原子操作需要硬件的支持,因此是架构相关的,其API和原子类型的定义都定义在内核源码树的include/asm/atomic.h文件中,它们都使用汇编语言实现,因为C语言并不能实现这样的操作。

1、atomic_t数据类型

原子操作主要用于实现资源计数,很多引用计数(refcnt)就是
通过原子操作实现的。原子类型定义如下
typedef struct
{ volatile int counter;} atomic_t;
volatile修饰字段告诉gcc不要对该类型的数据做优化处理,
对它的访问都是对内存的访问,而不是对寄存器的访问。

2、操作API

void atomic_read(atomic_t * v);
该函数对原子类型的变量进行原子读操作,它返回原子类型的变量v的值。
void atomic_set(atomic_t * v, int i);
该函数设置原子类型的变量v的值为i。
void atomic_add(int i, atomic_t *v);
该函数给原子类型的变量v增加值i。
void atomic_sub(int i, atomic_t *v);
该函数从原子类型的变量v中减去i。
int atomic_sub_and_test(int i, atomic_t *v);
该函数从原子类型的变量v中减去i,并判断结果是否为0,如果为0,返回真,否则返回假。
void atomic_inc(atomic_t *v);
该函数对原子类型变量v原子地增加1。
void atomic_dec(atomic_t *v);
该函数对原子类型的变量v原子地减1。
int atomic_dec_and_test(atomic_t *v);
该函数对原子类型的变量v原子地减1,并判断结果是否为0,如果为0,返回真,否则返回假。
int atomic_inc_and_test(atomic_t *v);
该函数对原子类型的变量v原子地增加1,并判断结果是否为0,如果为0,返回真,否则返回假。
int atomic_add_negative(int i, atomic_t *v);
该函数对原子类型的变量v原子地增加I,并判断结果是否为负数,如果是,返回真,否则返回假。
int atomic_add_return(int i, atomic_t *v);
该函数对原子类型的变量v原子地增加i,并且返回指向v的指针。
int atomic_sub_return(int i, atomic_t *v);
该函数从原子类型的变量v中减去i,并且返回指向v的指针。
int atomic_inc_return(atomic_t * v);
该函数对原子类型的变量v原子地增加1并且返回指向v的指针。
int atomic_dec_return(atomic_t * v);
该函数对原子类型的变量v原子地减1并且返回指向v的指针。

jiffies与HZ、定时器、原子操作相关推荐

  1. linux上的定时器上的jiffies,Linux kernel -- 定时器/jiffies

    0. 测试环境 Linux 2.6.39 AT91SAM9G45 1. 定时器简单的测试例子 #include #include MODULE_LICENSE("GPL"); st ...

  2. linux查看cpu的赫兹,linux平台jiffies和HZ Cpu使用率

    HZ:1秒钟内,时钟中断的次数,即1秒钟内,系统时钟的节拍次数. jiffies:全局变量,用来记录系统自启动以来产生的节拍总数 系统运行时间(以秒为单位):system_time=(jiffies) ...

  3. jiffies机制及其实验与使用 jiffies与HZ换算

    全局变量jiffies用来记录自系统启动以来产生的节拍的总数.启动时,内核将该变量初始化为0,此后,每次时钟中断处理程序都会增加该变量的值.一秒内时钟中断的次数等于Hz,所以jiffies一秒内增加的 ...

  4. 系统定时器、HZ、jiffies

    系统定时器 系统定时器是一种可编程硬件芯片,它能以固定频率产生中断,该频率可以通过编程预定,称作节拍率(tick rate),该中断就是定时器中断. 节拍率是通过静态预处理定义的,也就是 HZ,在系统 ...

  5. linux上的定时器上的jiffies,linux定时器和Jiffies汇.doc

    linux定时器和Jiffies汇 1.linux HZ Linux核心几个重要跟时间有关的名词或变数,将介绍HZ.tick与jiffies. HZ Linux核心每隔固定周期会发出timer int ...

  6. linux HZ Tick Jiffies

    1.linux HZ Linux核心几个重要跟时间有关的名词或变数,底下将介绍HZ.tick与jiffies. HZ Linux核心每隔固定周期会发出timer interrupt (IRQ 0),H ...

  7. Linux内核深入理解定时器和时间管理(1):硬件时钟和jiffies

    Linux内核深入理解定时器和时间管理 硬件时钟和jiffies rtoax 2021年3月 在原文基础上,增加5.10.13内核源码相关内容. 全局部变量 --------------------- ...

  8. arm linux hz,需要了解的linux HZ Tick Jiffies

    Linux核心几个重要跟时间有关的名词或变数,底下将介绍HZ.tick与jiffies. HZ Linux核心每隔固定周期会发出TImer interrupt (IRQ 0),HZ是用来定义每一秒有几 ...

  9. linux查询jiffies命令,linux HZ Tick Jiffies

    HZ的不同值会影响timer (节拍)中断的频率 2.2 jiffies及其溢出 全局变量jiffies取值为自操作系统启动以来的时钟滴答的数目,在头文 件中定义,数据类型为unsigned long ...

最新文章

  1. 凸现三围的健身运动法
  2. H3 BPM MVC表单SheetOffice控件使用分享
  3. 分库与分表设计-垂直切分
  4. python os.system关闭log_又到牛市!带你学习一个python强大证券数据分析工具
  5. android mysql 图片_android sqlite添加图片到数据库
  6. python网络爬虫系列(十)——chrome在爬虫中的使用
  7. python3 多继承搜索__init__方法的两种策略
  8. 【软件工程】业务过程与解决方案
  9. matlab ann-bp分类器,利用matlab真的BP-ANN分类器设计.doc
  10. 关于Keil4 转到 Keil5以后的一些错误解决
  11. 一文解锁加密算法的秘密
  12. Wcf传递的参数实际不为空,但是接收时显示为空。
  13. webpack分离打包css和less
  14. 它们把色情版 “微信” 的底裤都给挖出来了,网友: 草率了。。。
  15. 软件系统服务器端要求用千兆宽带,【硬核分享】升级千兆网络而速度却达不到?这些操作你做对了吗?...
  16. the JDBC Driver has been forcibly unregistered
  17. 解压ubi文件_IoT(八)ubi文件系统挂载解包
  18. 找出直系亲属 研究生机试 树
  19. 登录微软账户后远程桌面连接提示用户名错误
  20. [x y w h]转化为[ymin xmin ymax xmax]

热门文章

  1. BC3.1精简版win7/10下不兼容问题的解决
  2. [css]我要用css画幅画(七) - 哆啦A梦
  3. 新浪微博和腾讯微博图标
  4. 推荐一个开源库(Calligraphy)将ttf字体库加入到项目中,轻松实现各种字体
  5. 【FPGA】基于OV5640的 图像边沿检测
  6. sparklines_Sparklines入门200年来功能强大的数据可视化形式
  7. 六边形算法java_六边形架构 Java 实现
  8. 全国增值税发票查验平台 | 免验证码
  9. 下载夜神模拟器-安装autojs-连接vscode
  10. 支持3d android 模拟器,3D太空模拟器