转自:http://www.xuebuyuan.com/510594.html

5-3 Linux内核计时、延时函数与内核定时器

计时

1、 
内核时钟

1.1   
内核通过定时器(timer)中断来跟踪时间流

1.2   
硬件定时器以周期性的间隔产生时间中断,这个间隔(即频率)由内核根据HZ来确定,HZ是一个与体系结构无关的常数。

1.3   
这个时间间隔通常取1ms到10ms.

2、 
jiffies计算器

2.1每次当定时器中断发生时,内核内部通过一个64位的变量jiffies_64做加一计数。

2.2驱动程序开发者通常访问的是jiffies变量,它是jiffes_64的低32位。

2.3jiffies是unsigned
long型的变量,该变量被声明为volatile,这样可避免编译器对访问该变量的语句的优化。

2.4jiffies记录了自最近一次Linux启动后到当前的时间间隔(即时钟中断发生的次数)。驱动程序常利用jiffies来计算不同事件间的时间间隔。

3、HZ

3.1 HZ表每秒中产生的定时中断次数

3.2 HZ就代表1秒,HZ/2就代表0.5秒

4、使用jiffies计数器

#include<linux/jiffies.h>

Unsigned long  current_i,  stamp_1, 
stamp_half,  stamp_n;

Current_i = jiffies;  //读取当前的值

Stamp_1 = current_i+HZ;  //未来的一秒

Stamp_half = current_i +HZ/2 ; //未来的半秒

Stamp_n = current_i + n*HZ/1000; //未来的n毫秒

5、为了防止jiffies溢出导致问题,最好使用宏比较

#include<linux/jiffies.h>

Int time_after(unsigned long a, unsigned long b);//判断a代表的时间是否在b之后。

Int time_before(unsigned long a,unsigned long b);

Int time_after_eq(unsigned long a ,unsigned long b);

Int time_before_eq(unsigned long a,unsigned long b);

6、

(1)用户空间的timeval

struct timeval{

time_t tv_sev;//秒、

suseconds_t tv_usec;//毫秒

}

(2)用户空间的timespec

struct timespec{

time_t tv_sec;//秒

long  tv_nsec;//纳秒

}

7、内核空间jiffies和用户空间的timeval、timevspec的转换。

#include<linux/time.h>

unsigned long timespec_to_jiffies(struct timespec* value);

void jiffies_to_timespec(unsigned long jiffie,struct timespec* value);

unsigned long timeval_to_jiffies(struct timeval* value);

void jiffies_to_timeval(unsigned long jiffies, struct 
timeval* value);

8、获取当前时间

#include<linux/time.h>
   void do_gettimeofday(struct timeval*  
tv);

struct timespec current_kernel_time(void);

9、使用jiffies延时(如果对延时的精度要求不是很高时,用忙等待)

unsigned long j = jiffies + delay*HZ

while(jiffies<j){  //jiffies表当前的滴答值,是不停地走的。
  
/*do nothing*/

}

10、长延迟。

while(time_before(jiffies,end_time)){

Schedule();//在end_time之前,则调度

}

#include<linux/sched.h>
    signed long schedule_timeout(signed long timeout);//使用jiffies表示的延迟。先做超时,

典型应用:

set_current_state(TASK_INTERRUPTIBLE);//设置状态值,设置为可中断的睡眠

schedule_timeout(delay);//延时

11、短延时(忙等待延时,不发生休眠)

#include<linux/delay>

//以下三个延时函数均是忙等待函数,因而在延迟过程中午饭运行其他任务。不发生休眠的。

void ndelay(unsigned long nsecs); //延时纳秒

void udelay(unsigned long usecs);//延时微秒

void mdelay(unsigned long msecs);//延时毫秒

12、不用忙等待的延时方式(将调用进程休眠给定时间)

#include<linux/delay.h>

void msleep(unsigened int millisecs);//休眠millisecs毫秒
不可中断的休眠millisecs毫秒

unsigned long msleep_interruptible(unsigned int millisecs);//可中断的休眠

void ssleep(unsigned int seconds);//休眠seconds秒。

内核定时器:

13、定时器用于控制某个函数(定时器处理函数)在未来的某个特定时间执行。内核定时器注册的处理函数只执行一次—不是循环执行的。

14、内核定时器被组织成双向链表,并使用struct
time_list 结构描述。

#include<linux/timer.h>

struct timer_list{

unsigned long expires;  //超时的jiffies

void (*function)(unsigned long);//超时处理函数

unsigned long data; //超时处理函数参数。

};

15、内核定时器操作函数

15.1初始化(初始化定时器队列结构)

void init_timer(struct timer_list * timer);

struct timer_list TIMER_INITIALIZER(_function,_expires,_data);

15.2添加定时器(启动定时器,开始倒计时)

void add_timer(struct time_list *tiemer0:

15.3删除定时器(在定时器超时前将它删除。定时器超时后,系统会自动地将它删除)

15.4内核定时器使用模板

static struct timer_list  key_timer;//定义内核定时器对象

static void key_timer_handle(unsigned ong data)//定时器处理函数

{

……

//定时器处理函数具体执行代码

……

// 定时器参数的更新,重启定时器

key_timer.expires = jiffies+ KEY_TIMER_DELAY;

add_time(&key_time); 
 //赋新值,可以实现
循环

……

}

//设备驱动模块加载函数

static int__ init xxx_init(void)

{

……

//初始化内核定时器

init_time(&key_timer);

key_timer.function=&key_timer_handle;

key_timer.data = (unsigned long)key_desc;

key_timer.expires = jiffies+KEY_TIMER_DELAY;

//添加内核定时器(这是第一次启动)

add_time(&key_time);

……

}

Static void__exit xxx_exit(void)

{
              ……

//删除定时器

del_timer(&key_timer);

……

}

16、内核定时器与tasklet比较

16.1相同点:
在中断期间运行,时钟会在调度他们的同一个cpu上运行,软件中断的上下文,原子模式运行。(软件中断时打开硬件中断的同时执行某些异步任务的一种内核机制)

16.2不同的:不能要求TASKLECT在给定的时间执行。

声明:本文非原创,整理自申嵌

5-3 Linux内核计时、延时函数与内核定时器【转】的更多相关文章

  1. (转)linux下的系统调用函数到内核函数的追踪

    转载网址:http://blog.csdn.net/maochengtao/article/details/23598433 使用的 glibc : glibc-2.17使用的 linux kerne ...

  2. linux下的系统调用函数到内核函数的追踪

    http://blog.csdn.net/maochengtao/article/details/23598433

  3. C\C++中计时、延时函数

    转载:https://blog.csdn.net/keith_bb/article/details/53055380 C\C++标准库中提供了两种计时函数clock()和time().其用法如下:(1 ...

  4. linux中内核延时函数 (转)

    第一类延时函数原型是:(忙等) void ndelay(unsigned long nsecs); void udelay(unsigned long usecs); void mdelay(unsi ...

  5. Linux内核使用毫秒延时函数

    毫秒延时函数:mdelay() 微妙延时函数:ndelay() #ifndef mdelay #define mdelay(n) (/ (__builtin_constant_p(n) &&a ...

  6. linux内核申请内存函数

    kmap函数:    把某块高端内存映射到页表,然后返回给用户一个填好vitual字段的page结构    建立永久地址映射,不是简单的返回virtual字段的pageioremap:    驱动程序 ...

  7. Linux内核源码分析--内核启动之(5)Image内核启动(rest_init函数)(Linux-3.0 ARMv7)【转】

    前面粗略分析start_kernel函数,此函数中基本上是对内存管理和各子系统的数据结构初始化.在内核初始化函数start_kernel执行到最后,就是调用rest_init函数,这个函数的主要使命就 ...

  8. Linux内核源码分析--内核启动之(6)Image内核启动(do_basic_setup函数)(Linux-3.0 ARMv7)【转】

    原文地址:Linux内核源码分析--内核启动之(6)Image内核启动(do_basic_setup函数)(Linux-3.0 ARMv7) 作者:tekkamanninja 转自:http://bl ...

  9. Linux内核源码分析--内核启动之(4)Image内核启动(setup_arch函数)(Linux-3.0 ARMv7)【转】

    原文地址:Linux内核源码分析--内核启动之(4)Image内核启动(setup_arch函数)(Linux-3.0 ARMv7) 作者:tekkamanninja 转自:http://blog.c ...

随机推荐

  1. bzoj3502[PA2012]Tanie Linie(最大k区间和)

    题意:给定一个长为n的数列,要求选出最多k个不相交的区间(可以不选),使得选中的数字之和最大.(1<=k<=n<=1000000)分析:首先我们通过预处理对问题做一些简化.原序列中的 ...

  2. 【bzoj4444】[Scoi2015]国旗计划 倍增

    题目描述 给出一个圈和若干段,问:对于所有的 $i$ ,选择第 $i$ 段的情况下,最少需要选择多少段(包括第 $i$ 段)能够覆盖整个圈? 输入 第1行,包含2个正整数N,M,分别表示边防战士数量和 ...

  3. Django错误 OperationalError: no such column: xxx

    模型前后操作如下: 第一次迁移: class Snippet(models.Model): created = models.DateTimeField(auto_now_add=True) titl ...

  4. 安装单机Hadoop系统(完整版)——Mac

    在这个阴雨绵绵的下午,没有睡午觉的我带着一双惺忪的眼睛坐在了电脑前,泡上清茶,摸摸已是略显油光的额头(笑cry),,奋斗啊啊啊啊!!%>_<% 1.课程回顾. 1.1 Hadoop系统运行 ...

  5. javascript中的this作用域详解

    javascript中的this作用域详解 Javascript中this的指向一直是困扰我很久的问题,在使用中出错的机率也非常大.在面向对象语言中,它代表了当前对象的一个引用,而在js中却经常让我觉 ...

  6. BZOJ5289 & 洛谷4437:[HNOI/AHOI2018]排列——题解

    https://www.lydsy.com/JudgeOnline/problem.php?id=5289 https://www.luogu.org/problemnew/show/P4437 考虑 ...

  7. BZOJ2002:[HNOI2010]弹飞绵羊——题解

    http://www.lydsy.com/JudgeOnline/problem.php?id=2002 https://www.luogu.org/problemnew/show/P3203 某天, ...

  8. Java实验报告(实验四)

    北京电子科技学院(BESTI) 实     验    报     告 课程:Java    班级:1352班      姓名:王国伊    学号:20135207 成绩:             指导 ...

  9. 细谈select函数(C语言)

    Select在Socket编程中还是比较重要的,可是对于初学Socket的人来说都不太爱用Select写程序,他们只是习惯写诸如connect.accept.recv或recvfrom这样的阻塞程序( ...

  10. [samba]samba设置指定用户权限

    步骤: 1.在系统中添加用户 批量添加用户和密码的方法(因为samba用户要求必须在系统中存在): for name in a b c d;do useradd $name ; echo " ...