5-3 Linux内核计时、延时函数与内核定时器【转】
转自: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内核计时、延时函数与内核定时器【转】的更多相关文章
- (转)linux下的系统调用函数到内核函数的追踪
转载网址:http://blog.csdn.net/maochengtao/article/details/23598433 使用的 glibc : glibc-2.17使用的 linux kerne ...
- linux下的系统调用函数到内核函数的追踪
http://blog.csdn.net/maochengtao/article/details/23598433
- C\C++中计时、延时函数
转载:https://blog.csdn.net/keith_bb/article/details/53055380 C\C++标准库中提供了两种计时函数clock()和time().其用法如下:(1 ...
- linux中内核延时函数 (转)
第一类延时函数原型是:(忙等) void ndelay(unsigned long nsecs); void udelay(unsigned long usecs); void mdelay(unsi ...
- Linux内核使用毫秒延时函数
毫秒延时函数:mdelay() 微妙延时函数:ndelay() #ifndef mdelay #define mdelay(n) (/ (__builtin_constant_p(n) &&a ...
- linux内核申请内存函数
kmap函数: 把某块高端内存映射到页表,然后返回给用户一个填好vitual字段的page结构 建立永久地址映射,不是简单的返回virtual字段的pageioremap: 驱动程序 ...
- Linux内核源码分析--内核启动之(5)Image内核启动(rest_init函数)(Linux-3.0 ARMv7)【转】
前面粗略分析start_kernel函数,此函数中基本上是对内存管理和各子系统的数据结构初始化.在内核初始化函数start_kernel执行到最后,就是调用rest_init函数,这个函数的主要使命就 ...
- Linux内核源码分析--内核启动之(6)Image内核启动(do_basic_setup函数)(Linux-3.0 ARMv7)【转】
原文地址:Linux内核源码分析--内核启动之(6)Image内核启动(do_basic_setup函数)(Linux-3.0 ARMv7) 作者:tekkamanninja 转自:http://bl ...
- Linux内核源码分析--内核启动之(4)Image内核启动(setup_arch函数)(Linux-3.0 ARMv7)【转】
原文地址:Linux内核源码分析--内核启动之(4)Image内核启动(setup_arch函数)(Linux-3.0 ARMv7) 作者:tekkamanninja 转自:http://blog.c ...
随机推荐
- SPFA判負環
馬上就退役了,時間不足就不多介紹了 反正DFS是會T飛的,BFS就沒關係了qwq #include<cmath> #include<queue> #include<cst ...
- 【题解】Atcoder ARC#90 F-Number of Digits
Atcoder刷不动的每日一题... 首先注意到一个事实:随着 \(l, r\) 的增大,\(f(r) - f(l)\) 会越来越小.考虑暴力处理出小数据的情况,我们可以发现对于左端点 \(f(l) ...
- 【CodeChef】Palindromeness(回文树)
[CodeChef]Palindromeness(回文树) 题面 Vjudge CodeChef 中文版题面 题解 构建回文树,现在的问题就是要求出当前回文串节点的长度的一半的那个回文串所代表的节点 ...
- POJ2549:Sumsets——题解
http://poj.org/problem?id=2549 题目大意:从集合中找到四个不相同的数,满足a+b+c=d,输出最大的d. —————————————————————————— 该式子变为 ...
- IP协议简介
一.IP 1.IP是TCP/IP协议簇中最为核心的协议,所有的TCP.UDP.ICMP及IGMP数据都是以IP数据报格式传输. 2.IP提供不可靠.无连接的数据报传送服务 (1)不可靠:不保证IP数据 ...
- Java实验报告(实验四)
北京电子科技学院(BESTI) 实 验 报 告 课程:Java 班级:1352班 姓名:王国伊 学号:20135207 成绩: 指导 ...
- BZOJ1999 NOIP2007 洛谷P1099 P2491 SDOI 2011
Description: 设T=(V, E, W) 是一个无圈且连通的无向图(也称为无根树),每条边到有正整数的权,我们称T为树网(treebetwork),其中V,E分别表示结点与边的集合,W表示各 ...
- 学习tcpIp必备的抓包工具wireshark
wireshark是一个优秀的抓包工具 ip.src=192.168.10.123 发送http的一端 ip.dst=192.168.10.126 接收http的一端 如下图所示:
- 题解 【luogu P1541 NOIp提高组2010 乌龟棋】
题目链接 题解 题意: 有一些格子,每个格子有一定分数. 给你四种卡片,每次可以使用卡片来前进1或2或3或4个格子并拾取格子上的分数 每张卡片有数量限制.求最大分数. 分析 设\(dp[i]\)为第前 ...
- linux和windows多线程的异同
linux多线程及线程同步和windows的多线程之间的异同 并不是所有的程序都必须采用多线程,有时候采用多线程性能还不如单线程.采用多线程的好处如下: (1)多线程之间采用相同的地址空间,共享大部分 ...